BeanDefinitionRegistryPostProcessor和ClassPathBeanDefinitionScanner实现自定义注解的接口代理和注入

BeanDefinitionRegistryPostProcessor spring官方解释是:允许正常的BeanFactoryPostProcessor检测开始之前注册更多的自定义bean。特别是,BeanDefinitionRegistryPostProcessor可以注册更多的bean定义,然后定义BeanFactoryPostProcessor实例。也就是说可以借此方法实现自定义的bean。

BeanDefinitionRegistryPostProcessor继承了BeanBeanFactoryPostProcessor, 也就是说想实现自定义的bean 可以实现BeanDefinitionRegistryPostProcessor或者BeanBeanFactoryPostProcessor中的方法。通过springboot启动后发现这2个方法执行顺序有先后。

1、下面先看下通过BeanDefinitionRegistryPostProcessor实现简单的自定义bean:

@Configuration
public class BeanConfiger implements BeanDefinitionRegistryPostProcessor,ApplicationContextAware{
    private ApplicationContext applicationContext;
    private final static Logger LOGGER = LoggerFactory.getLogger(BeanConfiger.class);
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        LOGGER.info("postProcessBeanDefinitionRegistry执行!");
        /*RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(UserDomain.class);
        rootBeanDefinition.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
        rootBeanDefinition.getPropertyValues().add("name","pepsi");
        registry.registerBeanDefinition("userDomain",rootBeanDefinition);*/

        //使用不同beanDefinition
        Class cls = UserDomain.class;
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(cls);
        GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
        definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        definition.getPropertyValues().add("name","pepsi02");
        // 注册bean名,一般为类名首字母小写
        registry.registerBeanDefinition("userDomain", definition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        LOGGER.info("postProcessBeanFactory() 执行!");
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

通过新建beanDefinition直接注册上去。通过autowire直接就可以获取。spring是不是非常强大!!!!我也是最近才渐渐明白为什么spring可以作为一个基础框架和其他框架无缝连接。其中mybatis等第三方集成到spring都是通过FactoryBean、BeanDefinitionRegistryPostProcessor、ClassPathBeanDefinitionScanner实现。我自己跟着mybatis的加载过程,自己理了一把如下:

2、使用自定义注解和factorybean实现接口注入:

      a、先是通过BeanDefinitionRegistryPostProcessor 进行拦截

@Component
public class AnnotationScannerConfigurer implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor{

    private ApplicationContext applicationContext;

    private Logger LOGGER = LoggerFactory.getLogger(AnnotationScannerConfigurer.class);


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        LOGGER.info("postProcessBeanFactory() beanDefinition的个数=====>"+beanFactory.getBeanDefinitionCount());
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
         LOGGER.info("postProcessBeanDefinitionRegistry() beanDefinitionName=====>"+registry.getBeanDefinitionNames().toString());
        // 需要被代理的接口
        AnnotationScanner annotationScanner = new AnnotationScanner(registry);
        annotationScanner.setResourceLoader(applicationContext);
        // "com.pepsi.annotationproxy.service"是我 接口所在的包
        annotationScanner.scan("com.pepsi.annotationproxy.service");

    }
}

      b、扫描指定的路径,接口定义

public class AnnotationScanner extends ClassPathBeanDefinitionScanner{

    public AnnotationScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }
    @Override
    protected void registerDefaultFilters() {
        //扫描规则
//        this.addIncludeFilter(new AnnotationTypeFilter(Refrence.class));
        this.addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
    }
    @Override
    protected Set doScan(String... basePackages) {
        Set beanDefinitions = super.doScan(basePackages);
        for (BeanDefinitionHolder holder : beanDefinitions) {
            GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
            //BeanFactory.getBean的方法跟进去后有一个判断是不是FactroyBean类型的。如果是从FactroyBean.getObejct获取
            //RefrenceAnnotationFactoryBean 实现了FactoryBean
            definition.setBeanClass(RefrenceAnnotationFactoryBean.class);
            this.getRegistry().registerBeanDefinition(holder.getBeanName(), definition);
        }
        return beanDefinitions;
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

}

      c、通过FactoryBean实现接口代理

            

public class RefrenceAnnotationFactoryBean<T> implements FactoryBean<T> {

    public RefrenceAnnotationFactoryBean(){}

    @Override
    public T getObject() throws Exception {
        return (T) InterfaceProxy.newInstance(BizService.class);
    }

    @Override
    public Class getObjectType() {
        return BizService.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

public class InterfaceProxy implements InvocationHandler {


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("ObjectProxy execute:" + method.getName());
        String methodName = method.getName();
        String param = Arrays.toString(args);
        return "pepsi is param="+param;
    }
    public static <T> T newInstance(Class<T> innerInterface) {
        ClassLoader classLoader = innerInterface.getClassLoader();
        Class[] interfaces = new Class[] { innerInterface };
        InterfaceProxy proxy = new InterfaceProxy();
        return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
    }
}

以上3步,就实现了自定义注解的接口代理和注入。

测试如下:

@Refrence
public interface BizService {
    String getName(String name);
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Refrence {

}
@RunWith(SpringRunner.class)
@SpringBootTest
public class AnnotationProxyApplicationTests {
   
   @Autowired
   private BizService bizService;
   
   @Test
   public void contextLoads() {
      bizService.getName("pepsi");
   }

}

整个自定义注解的接口代理和注入已完成。


你可能感兴趣的:(spring)