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

原文地址:https://www.cnblogs.com/sniffs/p/13255264.html