zoukankan      html  css  js  c++  java
  • spring学习总结003 --- IOC容器启动源码(BeanFactoryPostProcessor)

    接着上一篇,继续总结;本章节总结refresh方法的invokeBeanFactoryPostProcessors方法

    在这之前先说一些和该方法相关的东西

    1、BeanFactoryPostProcessor

    Bean工厂后置处理器,一般用来在BeanFactory创建并标准化之后实例化之前对Bean进行“增强”,如修改BeanDefination等;著名的实现为:PropertySourcesPlaceholderConfigurer(用于在JDBC时支持配置解析)

    有两种常用的接口类:BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor

    BeanDefinitionRegistryPostProcessor是一种功能更丰富的BeanFactory后处理器,他在spring框架中处理优先级更高;

    2、PriorityOrdered、Ordered接口

    大型spring项目中,可能存在多个BeanFactoryPostProcessor,指定它们的执行顺序,可以通过实现PriorityOrdered、Ordered接口来确定执行顺序;

    (1)实现了PriorityOrdered接口的后置处理器优先级永远高于实现Ordered接口的后置处理器

    (2)同等条件下,getOrder方法返回值越小的后置处理器优先级越高

    示例:

    public class MyBeanFactoryPostProcessor1 implements BeanFactoryPostProcessor, PriorityOrdered {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            log.info("MyBeanFactoryPostProcessor1");
        }
    
        @Override
        public int getOrder() {
            return 3;
        }
    }
    public class MyBeanFactoryPostProcessor2 implements BeanFactoryPostProcessor, Ordered {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            log.info("MyBeanFactoryPostProcessor2");
        }
    
        @Override
        public int getOrder() {
            return 1;
        }
    }
    public class MyBeanFactoryPostProcessor3 implements BeanFactoryPostProcessor, Ordered {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            log.info("MyBeanFactoryPostProcessor3");
        }
    
        @Override
        public int getOrder() {
            return 2;
        }
    }

    执行结果:

    4、invokeBeanFactoryPostProcessors

    该方法用来执行用户定义的BeanFactoryPostProcessor(声明为bean或者通过ApplicationContext.addBeanFactoryPostProcessor来添加),流程为:

    (1)先执行BeanDefinitionRegistryPostProcessor类型以及通过ApplicationContext.addBeanFactoryPostProcessor添加的BeanFactoryPostProcessor

    (2)执行顺序为:实现PriorityOrdered接口的后置处理器  > 实现Ordered接口的后置处理器 > 未实现顺序接口的后置处理器

    (3)执行BeanFactoryPostProcessor类型的后置处理器,执行顺序为:实现PriorityOrdered接口的后置处理器  > 实现Ordered接口的后置处理器 > 未实现顺序接口的后置处理器

    // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
        }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
    
    // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
        if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
        }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
    
    // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    boolean reiterate = true;
    while (reiterate) {
        reiterate = false;
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
                reiterate = true;
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();
    }
    
    // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    
    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    5、使用注意事项

    不要在BeanFactoryPostProcessor中执行可能会实例化bean的操作!!为啥会有这样的限制呢?示例如下:

    @Getter
    @Setter
    @ToString
    @Component
    public class Info {
        private String age;
    }
    @Slf4j
    @Component
    public class ErrorBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            // 该方法会实例化User类型Bean
            Map<String, User> beansOfType = beanFactory.getBeansOfType(User.class);
            log.info("beansOfType:{}", beansOfType);
        }
    }
    @Slf4j
    public class Test9 {
    
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean8.xml");
            User user = context.getBean(User.class);
            log.info("user:{}", user.toString());
        }
    }

    执行结果:

    原因:

    自动装配注解@AutoWired和@Resource对应的处理类分别为AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,这两个类是BeanPostProcessor,在Bean被实例化后执行;

    从refresh方法中可以明确的看到:BeanFactoryPostProcessor的执行要先于BeanPostProcessor的注册以及执行,因此会有依赖注入为空的问题

    PS:使用XML文件声明依赖关系无此问题,因为XML配置文件采用的<property>标签,依赖注入时使用setProperty

  • 相关阅读:
    Kafka设计解析(二)- Kafka High Availability (上)
    Kafka设计解析(三)- Kafka High Availability (下)
    Kafka深度解析
    Cloudera Manager(CDH5)内部结构、功能包括配置文件、目录位置等
    Failed to start /etc/rc.d/rc.local Compatibility
    Offset Management For Apache Kafka With Apache Spark Streaming
    maven-assembly-plugin打包可执行的jar包
    How Cigna Tuned Its Spark Streaming App for Real-time Processing with Apache Kafka
    SystemTap Beginners Guide
    数据可视化的开源方案: Superset vs Redash vs Metabase (二)
  • 原文地址:https://www.cnblogs.com/sniffs/p/13255264.html
Copyright © 2011-2022 走看看