• 【spring-05】BeanFactory 后处理器


    第五讲 BeanFactory 后处理器

    1. BeanFactory 后处理器的作用:为BeanFactory提供扩展
    2. 常见的BeanFactory后处理器


    定义 Bean1Bean2Mapper1Mapper2Config 5个类

    • Bean2上面加上@Component
    • Config上加@Component注解和@ComponentScan注解,Config中通过@Bean注解定义Bean1
    • Mapper1Mapper2上加@Mapper注解

    Config

    @Component
    @ComponentScan("com/example/spring01/com/a05")
    public class Config {
    
        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }
    
        @Bean
        public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            return sqlSessionFactoryBean;
        }
    
        @Bean(initMethod = "init")
        public DruidDataSource dataSource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setUrl("jdbc:mysql://120.77.215.102:3306/czctest?characterEncoding=utf-8");
            dataSource.setUsername("root");
            dataSource.setPassword("czc521190");
            return dataSource;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Bean1和Bean2

    @Slf4j
    public class Bean1 {
    
        public Bean1(){
            log.info("我是被 spring 管理啦");
        }
    }
    -----------------------------------------
    @Component
    @Slf4j
    public class Bean2 {
        public Bean2(){
            log.info("我是被 spring 管理啦");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Mapper1和Mapper2

    @Mapper
    public interface Mapper1 {
    }
    ----------------------------
    @Mapper
    public interface Mapper2 {
    }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    TestBeanFactoryPostProcessors

    public class TestBeanFactoryPostProcessors {
    
        public static void main(String[] args) {
            // GenericApplicationContext 是一个【干净】的容器,默认不会添加任何后处理器,方便做测试
            GenericApplicationContext context = new GenericApplicationContext();
    
            context.registerBean("config",Config.class);
            // 解析@ComponentScan、@Bean、@Import、@ImportResource注解
            context.registerBean(ConfigurationClassPostProcessor.class);
            // 添加Bean工厂后处理器MapperScannerConfigurer,解析@MapperScan注解
            context.registerBean(MapperScannerConfigurer.class,db->{
                db.getPropertyValues().add("basePackage","com/example/spring01/com/a05/mapper");
            });
    
            // 初始化容器
            context.refresh();
    
    
            for (String name:context.getBeanDefinitionNames()){
                System.out.println("name--:"+name);
            }
    
            // 容器销毁
            context.close();
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    结论

    1. @Component@Bean对应的Bean工厂后处理器是ConfigurationClassPostProcessor
    2. @MapperScan对应的Bean工厂后处理器是MapperScannerConfigurer
    ComponentScan将加了
    @Controller,@Repository,@Service,@Component注解的类注册到spring容器中
    
    • 1
    • 2

    模拟ComponentScan实现

    public static void main(String[] args) throws Exception {
        // GenericApplicationContext 是一个【干净】的容器,默认不会添加任何后处理器,方便做测试
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config",Config.class);
        // 模拟@ComponentScan
        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
        if(componentScan != null){
            for (String s : componentScan.basePackages()) {
                System.out.println(s);
                //com.example.spring01.com.a05.component -> classpath*:com/example/spring01/com/a05/component/**/*.class
                String path =  "classpath*:" + s.replace(".","/") + "/**/*.class";
                System.out.println(path);
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                Resource[] resources = context.getResources(path);
                AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                for (Resource resource : resources) {
                    System.out.println("resource---"+resource);
                    MetadataReader reader = factory.getMetadataReader(resource);
                    AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
                    System.out.println("类名:"+ reader.getClassMetadata().getClassName());
                    System.out.println("是否加了 @Component 注解:" + annotationMetadata.hasAnnotation(Component.class.getName()));
                    System.out.println("是否加了 @Component派生 注解:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
                    // 如果加了@Component 注解 或在 @Component派生 注解
                    if(annotationMetadata.hasAnnotation(Component.class.getName() ) || annotationMetadata.hasMetaAnnotation(Component.class.getName())){
                        // 生成 beanDefinition
                        AbstractBeanDefinition bd =
                            BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
                        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
                        String beanName = generator.generateBeanName(bd, beanFactory);
                        beanFactory.registerBeanDefinition(beanName,bd);
                    }
                }
            }
        }
        // 初始化容器
        context.refresh();
    
        for (String name:context.getBeanDefinitionNames()){
            System.out.println("name--:"+name);
        }
        // 容器销毁
        context.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    自定义一个后处理器ComponentScanPostProcessor, 来解析@Component

    实现BeanFactoryPostProcessor两处修改

    1. context.getResources(path) -> new PathMatchingResourcePatternResolver().getResources(path);
      
      • 1
    2. DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
      -------------
      if(configurableListableBeanFactory instanceof DefaultListableBeanFactory){
          DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
          String beanName = generator.generateBeanName(bd, beanFactory);
          beanFactory.registerBeanDefinition(beanName,bd);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
            try {
                // 模拟@ComponentScan
                ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
                if(componentScan != null){
                    for (String s : componentScan.basePackages()) {
                        System.out.println(s);
                        //com.example.spring01.com.a05.component -> classpath*:com/example/spring01/com/a05/component/**/*.class
                        String path =  "classpath*:" + s.replace(".","/") + "/**/*.class";
                        System.out.println(path);
                        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                        AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                        for (Resource resource : resources) {
                            System.out.println("resource---"+resource);
                            MetadataReader reader = factory.getMetadataReader(resource);
                            AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
                            System.out.println("类名:"+ reader.getClassMetadata().getClassName());
                            System.out.println("是否加了 @Component 注解:" + annotationMetadata.hasAnnotation(Component.class.getName()));
                            System.out.println("是否加了 @Component派生 注解:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
                            // 如果加了@Component 注解 或在 @Component派生 注解
                            if(annotationMetadata.hasAnnotation(Component.class.getName() ) || annotationMetadata.hasMetaAnnotation(Component.class.getName())){
                                // 生成 beanDefinition
                                AbstractBeanDefinition bd =
                                        BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
    
                                if(configurableListableBeanFactory instanceof DefaultListableBeanFactory){
                                    DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
                                    String beanName = generator.generateBeanName(bd, beanFactory);
                                    beanFactory.registerBeanDefinition(beanName,bd);
                                }
    
                            }
                        }
                    }
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    引用自己写的后处理器

    public static void main(String[] args) throws Exception {
        // GenericApplicationContext 是一个【干净】的容器,默认不会添加任何后处理器,方便做测试
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config",Config.class);
    
        context.registerBean(ComponentScanPostProcessor.class);
        // 初始化容器
        context.refresh();
    
        for (String name:context.getBeanDefinitionNames()){
            System.out.println("name--:"+name);
        }
        // 容器销毁
        context.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    自定义一个CandyComponentScanPostProcessor 来解析@Component注解

    实现BeanDefinitionRegistryPostProcessor

    两次修改

    1. context.getResources(path) -> new PathMatchingResourcePatternResolver().getResources(path);
      
      • 1
    2. 去掉DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
      
      • 1
    public class CandyComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
           try {
               // 模拟@ComponentScan
               ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
               if(componentScan != null){
                   for (String s : componentScan.basePackages()) {
                       System.out.println(s);
                       //com.example.spring01.com.a05.component -> classpath*:com/example/spring01/com/a05/component/**/*.class
                       String path =  "classpath*:" + s.replace(".","/") + "/**/*.class";
                       System.out.println(path);
                       CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                       Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                       AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                       for (Resource resource : resources) {
                           System.out.println("resource---"+resource);
                           MetadataReader reader = factory.getMetadataReader(resource);
                           AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
                           System.out.println("类名:"+ reader.getClassMetadata().getClassName());
                           System.out.println("是否加了 @Component 注解:" + annotationMetadata.hasAnnotation(Component.class.getName()));
                           System.out.println("是否加了 @Component派生 注解:" + annotationMetadata.hasMetaAnnotation(Component.class.getName()));
                           // 如果加了@Component 注解 或在 @Component派生 注解
                           if(annotationMetadata.hasAnnotation(Component.class.getName() ) || annotationMetadata.hasMetaAnnotation(Component.class.getName())){
                               // 生成 beanDefinition
                               AbstractBeanDefinition bd =
                                       BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
                               String beanName = generator.generateBeanName(bd, beanFactory);
                               beanFactory.registerBeanDefinition(beanName,bd);
                           }
                       }
                   }
               }
           }catch (IOException e) {
               e.printStackTrace();
           }
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    工程后处理器模拟实现@Bean

    CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
    MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/example/spring01/com/a05/Config.class"));
    Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
    for (MethodMetadata method : methods) {
        System.out.println("method:" + method);
    
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        builder.setFactoryMethodOnBean(method.getMethodName(),"config");
        builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        AbstractBeanDefinition bd = builder.getBeanDefinition();
        context.getDefaultListableBeanFactory().registerBeanDefinition(method.getMethodName(),bd);
    
        String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
        if(initMethod.length() >0 ){
            builder.setInitMethodName(initMethod);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    实现BeanFactoryPostProcessor

    AtBeanPostProcessor 类

    public class AtBeanPostProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
            try {
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/example/spring01/com/a05/Config.class"));
                Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
                for (MethodMetadata method : methods) {
                    System.out.println("method:" + method);
    
                    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                    builder.setFactoryMethodOnBean(method.getMethodName(),"config");
                    builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
                    AbstractBeanDefinition bd = builder.getBeanDefinition();
                    if(configurableListableBeanFactory instanceof DefaultListableBeanFactory) {
                        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
                        beanFactory.registerBeanDefinition(method.getMethodName(), bd);
                    }
                    String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
                    if(initMethod.length() >0 ){
                        builder.setInitMethodName(initMethod);
                    }
                }
    
            }catch (Exception e){
    
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    工厂后处理器模拟实现—Mapper

    在Config,使用@Bean 注册

     @Bean
        public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory){
            MapperFactoryBean<Mapper1> factoryBean = new MapperFactoryBean<>(Mapper1.class);
            factoryBean.setSqlSessionFactory(sqlSessionFactory);
            return factoryBean;
        }
    
        @Bean
        public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory){
            MapperFactoryBean<Mapper2> factoryBean = new MapperFactoryBean<>(Mapper2.class);
            factoryBean.setSqlSessionFactory(sqlSessionFactory);
            return factoryBean;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    自定义 MapperPostProcessor

    这里不能使用名字生成器和MapperFactoryBean的BeanDefinition作为参数直接生成名字,这样会导致多个相同的类型的对象因为名字一样产生覆盖的问题
    解决办法 这里参考Spring源码的做法用@Mapper注解修饰的接口的BeanDefinition作为参数生成名字

    public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
            try {
                PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
                Resource[] resources = resolver.getResources("classpath:com/example/spring01/com/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) {
                throw new RuntimeException(e);
            }
    
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    136.只出现一次的数字
    Java面向对象(基础)-- 类的成员之三:构造器(Constructor)
    D. For Gamers. By Gamers.(思维 + dp + 二分)(调和级数)
    王道数据结构——树
    ABAP-SAP-整合事务码,整合平台,运维工具箱
    Feign 实现 GET 方法传递 POJO
    Doris学习笔记之介绍、编译安装与部署
    hevc 半像素
    Tesseract OCR安装与简单使用
    SAP-QM-UD取消程序
  • 原文地址:https://blog.csdn.net/qq_25614773/article/details/126257395