spring 05 BeanFactory 后处理器

BeanFactory 后处理器的作用

  • ConfigurationClassPostProcessor 可以解析
    • @ComponentScan
    • @Bean
    • @Import
    • @ImportResource
ConfigurationClassPostProcessor 具体作用
对于候选配置类使用CGLIB Enhancer增强

解析处理@PropertySource 注解

解析@ComponentScan注解,扫描@Configuration、@Service、@Controller、@Repository和@Component注解并注册BeanDefinition

解析@Import注解,然后进行实例化,并执行ImportBeanDefinitionRegistrar的registerBeanDefinitions逻辑,或者ImportSelector的selectImports逻辑

解析@ImportResource注解,并加载相关配置信息

解析方法级别@Bean注解并将返回值注册成BeanDefinition

注册ImportRegistry到容器中,用于处理ImportAware
  • MapperScannerConfigurer 可以解析
    • Mapper 接口
      需要提前注册 DataSource 和 SqlSessionFactoryBean 否则报错
点击查看代码
        //创建干净的容器
        GenericApplicationContext context = new GenericApplicationContext();
        //将 Bean 加入容器
        context.registerBean("s05Config",S05Config.class);
        //加入 BeanFactory 后处理器
        context.registerBean(ConfigurationClassPostProcessor.class);// 解析 @Bean、@ComponentScan、@Import、@ImportResource 等
        //加入 Mybatis 提供的后处理器,解析 @Mapper
        context.registerBean(MapperScannerConfigurer.class,bd->{
            bd.getPropertyValues().add("basePackage","cn.xyf.spring.s05");});

        //刷新容器
        context.refresh();
  1. @ComponentScan, @Bean, @Mapper 等注解的解析属于核心容器(即 BeanFactory)的扩展功能

  2. 这些扩展功能由不同的 BeanFactory 后处理器来完成,其实主要就是补充了一些 bean 定义

模拟解析 @ComponentScan

  1. Spring 操作元数据的工具类 CachingMetadataReaderFactory
  2. 通过注解元数据(AnnotationMetadata)获取直接或间接标注的注解信息
  3. 通过类元数据(ClassMetadata)获取类名,AnnotationBeanNameGenerator 生成 bean 名
  4. 解析元数据是基于 ASM 技术
自定义解析 @ComponentScan 处理器
public class MyComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override// context.refresh 初始化
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    @SneakyThrows
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory)throws BeansException {

        //解析 @ComponentScan 利用 Spring 提供的工具类 AnnotationUtils
        //1.得到 componentScan 注解
        ComponentScan componentScan = AnnotationUtils.findAnnotation(S05Config.class, ComponentScan.class);

        if (!Objects.isNull(componentScan)) {
            //2.得到注解上的包名信息
            for (String bp : componentScan.basePackages()) {
                //3.拼接字符串变为资源路径
                String path = "classpath*:" + bp.replace(".", "/") + "/**/*.class";
                //4.根据路径得到资源
                Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                //5.遍历资源通过 CachingMetadataReaderFactory 解析资源
                CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
                for (Resource resource : resources) {
                    MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource); //不走类加载,效率高
//                    System.out.println("类名是" + metadataReader.getClassMetadata().getClassName());
//                    System.out.println("是否有 @Component 注解" + metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
//                    System.out.println("是否有 @Component 派生注解" + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
                    //6.判断是否加了 @Component 注解或其派生注解
                    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                    if (annotationMetadata.hasAnnotation(Component.class.getName()) ||
                            annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
                        //7.将其变成 BeanDefinition 注册到容器中
                        //7.1通过 BeanDefinitionBuilder 得到 BeanDefinition
                        AbstractBeanDefinition beanDefinition
                                = BeanDefinitionBuilder.genericBeanDefinition(annotationMetadata.getClassName()).getBeanDefinition();
                        //7.2通过 AnnotationBeanNameGenerator 生成 BeanDefinition 的名字
                        AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
                        String beanName = annotationBeanNameGenerator.generateBeanName(beanDefinition, beanFactory);
                        //7.3通过 BeanFactory 注册 BeanDefinition
                        beanFactory.registerBeanDefinition(beanName,beanDefinition);
                    }
                }
            }
        }
    }
}

模拟解析 @Bean
熟悉注解元数据(AnnotationMetadata)获取方法上注解信息

点击查看代码
public class MyAtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry context) throws BeansException {

        try {
            CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
            MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(new ClassPathResource("cn/xyf/spring/s05/S05Config.class"));
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            Set<MethodMetadata> methods = annotationMetadata.getAnnotatedMethods(Bean.class.getName());
            for (MethodMetadata method : methods) {
                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
                BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
                BeanDefinitionBuilder builder =
                        beanDefinitionBuilder.setFactoryMethodOnBean(method.getMethodName(), "s05Config");
                builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
                if (initMethod.length() > 0) {
                    builder.setInitMethodName(initMethod);
                }
                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
                context.registerBeanDefinition(method.getMethodName(),beanDefinition);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("初始化了");
    }
}

模拟解析 Mapper 接口

  @Bean
    public MapperFactoryBean<S05Mapper1> s05Mapper1(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<S05Mapper1> factoryBean = new MapperFactoryBean<>(S05Mapper1.class);
        factoryBean.setSqlSessionFactory(sqlSessionFactory);
        return factoryBean;
    }
    @Bean
    public MapperFactoryBean<S05Mapper2> s05Mapper2(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<S05Mapper2> factoryBean = new MapperFactoryBean<>(S05Mapper2.class);
        factoryBean.setSqlSessionFactory(sqlSessionFactory);
        return factoryBean;
    }
  1. Mapper 接口被 Spring 管理的本质:实际是被作为 MapperFactoryBean 注册到容器中

  2. Spring 的诡异做法,根据接口生成的 BeanDefinition 仅为根据接口名生成 bean 名

点击查看代码
public class MyMapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
           try {
               PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver
                       = new PathMatchingResourcePatternResolver();
               AnnotationBeanNameGenerator annotationBeanNameGenerator = new AnnotationBeanNameGenerator();
               Resource[] resources =
                       pathMatchingResourcePatternResolver.getResources("classpath:cn/xyf/spring/s05/mapper/**/*.class");
               CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
               for (Resource resource : resources) {
                   MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
                   System.out.println(metadataReader.getClassMetadata().getClassName());
                   ClassMetadata classMetadata = metadataReader.getClassMetadata();
                   if (classMetadata.isInterface()) {
                       AbstractBeanDefinition beanDefinition
                               = BeanDefinitionBuilder
                               .genericBeanDefinition(MapperFactoryBean.class)
                               .addConstructorArgValue(classMetadata.getClassName())  //添加构造的参数
                               .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                               .getBeanDefinition();
                       AbstractBeanDefinition mapperBD =
                               BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getRawBeanDefinition();
                       String beanName = annotationBeanNameGenerator.generateBeanName(mapperBD, beanFactory);
                       beanFactory.registerBeanDefinition(beanName, beanDefinition);
                   }
               }
           } catch (IOException e) {
            e.printStackTrace();
        }
    }
posted @ 2022-06-17 15:01  xy7112  阅读(57)  评论(0)    收藏  举报