关于spring:spring扫描自定义注解对应的类并装入IOC容器

前言

本文继笔者学习mybatis源码后,仿照mybatis利用spring的拓展点将Mapper接口的代理类装入IOC的办法,实现自定义注解,让spring将指定包中有此注解的类拆卸进IOC容器来治理之,最终是放入容器的单例池中。

实现

1. 自定义注解

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

2. XxgComponentScannerConfigurer

2.1 实现BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor,是spring给咱们的一个拓展点,其本身继承自BeanFactoryPostProcessor接口。
实现此接口的类,spring在初始化之后,会调用其以下两个办法:

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;

故咱们能够在其实现类对应的办法中,执行咱们的业务逻辑–即让spring扫描咱们自定义注解对应的类。

2.2 代码

public class XxgComponentScannerConfigurer implements BeanDefinitionRegistryPostProcessor {
     private String basePackages;
     public void setBasePackages(String basePackages) {
            this.basePackages = basePackages;
     }
     @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
            // left intentionally blank
     }
     @Override
     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            XxgComponentScanner scanner = new XxgComponentScanner(registry);
         scanner.registerFilters();
         scanner.scan(basePackages);
     }
}

3.扫描类XxgComponentScanner

3.1 ClassPathBeanDefinitionScanner

此类是spring用于扫描bean的类,

  1. doScan()办法会依据配置的拦截器规定,来将须要的类装配成BeanDefinitionHolder对象并返回。
  2. 调用其scan()办法,其本身先调用doScan()办法,而后会将扫描到的BeanDefinitionHolder对象放入IOC容器

故,咱们能够继承其类,而后:

  1. 不应用其默认拦挡规定,而是依据咱们自定义注解来拦挡
  2. 重写其doScan()办法,首先调用父类的doScan()获取到有咱们自定义注解的BeanDefinitionHolder对象们,而后能够遍历操作之,更改一些咱们须要的参数,比方设置scope为单例等。

3.2 代码

public class XxgComponentScanner extends ClassPathBeanDefinitionScanner {
    public XxgComponentScanner(BeanDefinitionRegistry registry) {
        // 第二个参数:useDefaultFilters
        // 设置为false,不应用默认拦截器
        super(registry, false);
    }
    @Override
     public Set<BeanDefinitionHolder> doScan(String... basePackages) {
            // 利用spring的扫描办法,扫描mapper接口所在的包,获取所有BeanDefinitionHolder
         Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
         processBeanDefinitions(beanDefinitions);
         return beanDefinitions;
     }
     private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitionHolders) {
        for (BeanDefinitionHolder holder : beanDefinitionHolders) {
            GenericBeanDefinition beanDefinition = (GenericBeanDefinition)holder.getBeanDefinition();
 beanDefinition.setScope("singleton");
        System.out.println(beanDefinition.getBeanClassName());
        }
    }
    // 定义拦截器,让spring拆卸咱们须要的对象到IOC容器
    public void registerFilters() {
        // 设置 只扫描有@XxgComponent注解的类
     addIncludeFilter(new AnnotationTypeFilter(XxgComponent.class));
     // 设置 疏忽 package-info.java addExcludeFilter((metadataReader, metadataReaderFactory) -> {
                String className = metadataReader.getClassMetadata().getClassName();
        return className.endsWith("package-info");
     });
   }
}

4.让spring治理咱们的XxgComponentScannerConfigurer

<!-- 测试自定义拆卸bean注解-->
 <bean class="com.dbc.springMybatis.util.XxgComponentScannerConfigurer">
   <property name="basePackages" value="com.dbc.springMybatis.myBean"/>
 </bean>

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理