接着上一篇,继续总结;本章节总结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