2

BeanDefinitionRegistryPostProcessor扩展

 2 years ago
source link: https://wakzz.cn/2019/12/29/springboot/BeanDefinitionRegistryPostProcessor%E6%89%A9%E5%B1%95/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

BeanDefinitionRegistryPostProcessor扩展

祈雨的博客
2019-12-29

通过BeanDefinitionRegistryPostProcessor扩展能实现额外的很多功能,例如实现将一个接口动态代理,并将该代理对象在spring容器初始化完成前注册到spring容器中。实现可以通过@Autowired等注释或其他方法从spring容器中获取该代理对象。

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";
}

}
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;
}

}
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;
}

/**
* 只扫描出指定Annotation注解的类
*/
public void registerFilters() {
if (this.annotationClass != null) {
addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
}

// exclude package-info.java
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;
}

/**
* 将扫描出的类实现代理类,并注册到spring中
*/
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);
}
}
}
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) {
}
}
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 {
}
import com.wakzz.autowire.Reference;

@Reference
public interface TestService {

String sayHello();

}
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;
}

}
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder()
.sources(Application.class)
.run(args);
TestService bean = applicationContext.getBean(TestService.class);
String response = bean.sayHello();
System.out.println(response);

最终输出如下:

2019-12-29 15:37:35.938  INFO 25336 --- [           main] com.wakzz.autowire.proxy.HelloProxy      : 调用代理方法, method: sayHello
hello world

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK