通过BeanDefinitionRegistryPostProcessor
扩展能实现额外的很多功能,例如实现将一个接口动态代理,并将该代理对象在spring容器初始化完成前注册到spring容器中。实现可以通过@Autowired等注释或其他方法从spring容器中获取该代理对象。
代理工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
@Slf4j public class HelloProxy implements InvocationHandler {
private Class<?> interfaceClass;
public Object bind(Class<?> cls) { this.interfaceClass = cls; return Proxy.newProxyInstance(cls.getClassLoader(), new Class[]{interfaceClass}, this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) { log.info("调用代理方法, method: {}", method.getName()); return "hello world"; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import org.springframework.beans.factory.FactoryBean;
public class ProxyBeanFactory<T> implements FactoryBean<T> {
private Class<T> interfaceClass;
public Class<T> getInterfaceClass() { return interfaceClass; }
public void setInterfaceClass(Class<T> interfaceClass) { this.interfaceClass = interfaceClass; }
@Override public T getObject() { return (T) new HelloProxy().bind(interfaceClass); }
@Override public Class<?> getObjectType() { return interfaceClass; }
@Override public boolean isSingleton() { return true; }
}
|
扫描注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| import com.wakzz.autowire.proxy.ProxyBeanFactory; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.TypeFilter;
import java.lang.annotation.Annotation; import java.util.Set;
public class ClassPathReferenceScanner extends ClassPathBeanDefinitionScanner {
private BeanDefinitionRegistry registry; private Class<? extends Annotation> annotationClass;
public ClassPathReferenceScanner(BeanDefinitionRegistry registry) { super(registry, false); this.registry = registry; }
public void setAnnotationClass(Class<? extends Annotation> annotationClass) { this.annotationClass = annotationClass; }
public void registerFilters() { if (this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter(this.annotationClass)); }
addExcludeFilter(new TypeFilter() { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) { String className = metadataReader.getClassMetadata().getClassName(); return className.endsWith("package-info"); } }); }
@Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); }
@Override public Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); processBeanDefinitions(beanDefinitions); return beanDefinitions; }
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { for (BeanDefinitionHolder holder : beanDefinitions) { String className = holder.getBeanDefinition().getBeanClassName();
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(className); GenericBeanDefinition proxyDefinition = (GenericBeanDefinition) builder.getRawBeanDefinition(); proxyDefinition.getPropertyValues().add("interfaceClass", className); proxyDefinition.setBeanClass(ProxyBeanFactory.class); proxyDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); this.registry.registerBeanDefinition(holder.getBeanName(), proxyDefinition); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware;
import java.lang.annotation.Annotation;
public class ReferenceRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
private String basePackage;
private Class<? extends Annotation> annotationClass;
private ApplicationContext applicationContext;
public void setBasePackage(String basePackage) { this.basePackage = basePackage; }
public void setAnnotationClass(Class<? extends Annotation> annotationClass) { this.annotationClass = annotationClass; }
@Override public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; }
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { ClassPathReferenceScanner scanner = new ClassPathReferenceScanner(registry); scanner.setAnnotationClass(this.annotationClass); scanner.setResourceLoader(this.applicationContext); scanner.registerFilters(); scanner.scan(basePackage); }
@Override public void afterPropertiesSet() { }
@Override public void setBeanName(String name) { } }
|
注入实现
1 2 3 4 5 6 7 8 9
| import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Reference { }
|
1 2 3 4 5 6 7 8
| import com.wakzz.autowire.Reference;
@Reference public interface TestService {
String sayHello();
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import com.wakzz.autowire.Reference; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class ReferenceConfig {
@Bean public BeanDefinitionRegistryPostProcessor referenceRegistryPostProcessor() { ReferenceRegistryPostProcessor referenceRegistryPostProcessor = new ReferenceRegistryPostProcessor(); referenceRegistryPostProcessor.setAnnotationClass(Reference.class); referenceRegistryPostProcessor.setBasePackage("com.wakzz.autowire"); return referenceRegistryPostProcessor; }
}
|
效果
1 2 3 4 5 6
| ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder() .sources(Application.class) .run(args); TestService bean = applicationContext.getBean(TestService.class); String response = bean.sayHello(); System.out.println(response);
|
最终输出如下:
1 2
| 2019-12-29 15:37:35.938 INFO 25336 --- [ main] com.wakzz.autowire.proxy.HelloProxy : 调用代理方法, method: sayHello hello world
|