05.BeanFactory后处理器

文章介绍了BeanFactory后处理器在Spring中的作用,它是如何扩展BeanFactory的功能,如处理@Configuration、@ComponentScan、@Bean、@Mapper等注解。通过示例展示了如何注册并使用ConfigurationClassPostProcessor和MapperScannerConfigurer。同时,文章详细讲解了如何自定义BeanDefinitionRegistryPostProcessor来处理@Component、@Bean和@Mapper注解,实现了扫描和注册相关类的功能。
摘要由CSDN通过智能技术生成

BeanFactory后处理器

  1. BeanFactory后处理器的作用:为 BeanFactory 提供扩展;@ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能,这些扩展功能由不同的BeanFactory后处理器来完成, 其实主要就是补充了一些 bean 定义
  2. 常见的 BeanFactory 后处理器
  3. 实现自己的BeanFactory后处理器

一 常见BeanFactory后处理器

  1. ConfigurationClassPostProcessor :扫描@Config @Bean @ComponentScan @Component @Controller 等注解
  2. MapperScannerConfigurer: 扫描@MapperSanner @Mapper 等注解

使用方式

		public static void main(String[] args) {

        // GenericApplicationContext 是一个【干净】的容器
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);

        // @ComponentScan @Bean @Import @ImportResource
        context.registerBean(ConfigurationClassPostProcessor.class);
        // @MapperScanner
        context.registerBean(MapperScannerConfigurer.class, beanDefinition -> {
            beanDefinition.getPropertyValues().add("basePackage", "com.shunyum.a05.mapper");
        });

        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        context.close();
    }

二 实现自己的BeanFactory后处理器

自定义一个类,实现BeanDefinitionRegisterPostProcess接口,重写postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法;该方法本质上就是通过识别类和类中的方法上的注解,对定义的Bean进行处理。

重点为下面几个类:

  1. PathMatchingResourcePatternResolver:表达式匹配资源,通过resolver.getResource(str)来获取某个目录下的资源Resources;
  2. CachingMetadataReaderFactory:元数据处理工厂,通过facotry.getMetaDataReader(resouce)来获取一个MetaDataReadaer对象,该对象包含类的类名、包含的方法、注解等信息;
  3. MetadataReader:通过该对象来进行一系列的操作,例如metaDataReader.getAnnotationMetaData()来获取该类上添加的注解

注:BeanDefinitionRegisterPostProcess继承自BeanFacotryPostProcessor

2.1 自定义Bean工厂后处理器来处理@Component注解
public class MyComponentScan implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        try {
            ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            if (Objects.nonNull(componentScan)) {
                for (String basePackage : componentScan.basePackages()) {
                    // com.shunyum.a05
                    // classpath*:com/shunyum/a05/**/*.class
                    String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";

                    CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();

                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);

                    AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
                    for (Resource resource : resources) {
                        MetadataReader metadataReader = factory.getMetadataReader(resource);
                        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

                        if (annotationMetadata.hasAnnotation(Component.class.getName())
                                || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {

                            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                                    .genericBeanDefinition(metadataReader.getClassMetadata().getClassName())
                                    .getBeanDefinition();

                            String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition,
                                    registry);
                            registry.registerBeanDefinition(beanName, beanDefinition);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
2.2 自定义Bean工厂后处理器来处理@Bean注解
public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        try {
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            MetadataReader metadataReader = factory.getMetadataReader(new ClassPathResource("com/shunyum/a05/Config.class"));

            Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
            for (MethodMetadata method : annotatedMethods) {
                System.out.println(method);
                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition()
                        .setFactoryMethodOnBean(method.getMethodName(), "config")
                        // 解决通过@Bean方法创建Bean时的自动注入
                        .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR)
                        // 处理initMethod属性
                        .setInitMethodName(initMethod)
                        ;
                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
                registry.registerBeanDefinition(method.getMethodName(), beanDefinition);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
2.3 自定义Bean工厂后处理器来处理@Mapper注解
public class MyMapperScan implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
        try {
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources("classpath:com/shunyum/a05/mapper/**/*.class");
            AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
            for (Resource resource : resources) {
                MetadataReader reader = factory.getMetadataReader(resource);
                ClassMetadata classMetadata = reader.getClassMetadata();
                if (classMetadata.isInterface()) {
                    AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                            .addConstructorArgValue(classMetadata.getClassName())
                            .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                            .getBeanDefinition();
                    AbstractBeanDefinition bd2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
                    String name = generator.generateBeanName(bd2, beanFactory);
                    beanFactory.registerBeanDefinition(name, bd);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值