栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【spring-05】BeanFactory 后处理器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【spring-05】BeanFactory 后处理器

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

文章目录
  • 第五讲 BeanFactory 后处理器
      • TestBeanFactoryPostProcessors
      • 结论
      • 模拟ComponentScan实现
      • 自定义一个后处理器ComponentScanPostProcessor, 来解析@Component
      • 自定义一个CandyComponentScanPostProcessor 来解析`@Component`注解
      • 工程后处理器模拟实现@Bean
      • 实现BeanFactoryPostProcessor
      • 工厂后处理器模拟实现—Mapper
      • 自定义 MapperPostProcessor

定义 Bean1、 Bean2、 Mapper1、 Mapper2、 Config 5个类

  • Bean2上面加上@Component
  • Config上加@Component注解和@ComponentScan注解,Config中通过@Bean注解定义Bean1
  • Mapper1、Mapper2上加@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;
    }
}

Bean1和Bean2

@Slf4j
public class Bean1 {

    public Bean1(){
        log.info("我是被 spring 管理啦");
    }
}
-----------------------------------------
@Component
@Slf4j
public class Bean2 {
    public Bean2(){
        log.info("我是被 spring 管理啦");
    }
}

Mapper1和Mapper2

@Mapper
public interface Mapper1 {
}
----------------------------
@Mapper
public interface Mapper2 {
}
    
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. @Component、@Bean对应的Bean工厂后处理器是ConfigurationClassPostProcessor;
  2. @MapperScan对应的Bean工厂后处理器是MapperScannerConfigurer。
ComponentScan将加了
@Controller,@Repository,@Service,@Component注解的类注册到spring容器中
模拟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();
}
自定义一个后处理器ComponentScanPostProcessor, 来解析@Component

实现BeanFactoryPostProcessor两处修改

  1. context.getResources(path) -> new PathMatchingResourcePatternResolver().getResources(path);
    
  2. DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
    -------------
    if(configurableListableBeanFactory instanceof DefaultListableBeanFactory){
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
        String beanName = generator.generateBeanName(bd, beanFactory);
        beanFactory.registerBeanDefinition(beanName,bd);
    }
    
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();
        }
    }
}

引用自己写的后处理器

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();
}
自定义一个CandyComponentScanPostProcessor 来解析@Component注解

实现BeanDefinitionRegistryPostProcessor

两次修改

  1. context.getResources(path) -> new PathMatchingResourcePatternResolver().getResources(path);
    
  2. 去掉DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
    
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 {

    }
}
工程后处理器模拟实现@Bean
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/example/spring01/com/a05/Config.class"));
Set 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);
    }
}
实现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 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){

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

在Config,使用@Bean 注册

 @Bean
    public MapperFactoryBean mapper1(SqlSessionFactory sqlSessionFactory){
        MapperFactoryBean factoryBean = new MapperFactoryBean<>(Mapper1.class);
        factoryBean.setSqlSessionFactory(sqlSessionFactory);
        return factoryBean;
    }

    @Bean
    public MapperFactoryBean mapper2(SqlSessionFactory sqlSessionFactory){
        MapperFactoryBean factoryBean = new MapperFactoryBean<>(Mapper2.class);
        factoryBean.setSqlSessionFactory(sqlSessionFactory);
        return factoryBean;
    }

自定义 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 {

    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1039764.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号