本文作者:chenssy
出处:http://cmsblogs.com/?p=3338
在学习Spring源码
的过程中发现的好站+好贴,感谢作者。Spring版本:Spring 5.0.6.RELEASE
Spring 作为优秀的开源框架,它为我们提供了丰富的可扩展点,除了前面提到的 Aware 接口,还包括其他部分,其中一个很重要的就是 BeanPostProcessor。
这篇文章主要介绍 BeanPostProcessor 的使用以及其实现原理。我们先看 BeanPostProcessor 的定位:
BeanPostProcessor 的作用:在 Bean 完成实例化后,如果我们需要对其进行一些配置、增加一些自己的处理逻辑,那么请使用 BeanPostProcessor。
BeanPostProcessor 实例 首先定义一个类,该类实现 BeanPostProcessor 接口,如下:
public class BeanPostProcessorTest implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { System.out.println("Bean [" + beanName + "] 开始初始化" ); return bean; } @Override public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { System.out.println("Bean [" + beanName + "] 完成初始化" ); return bean; } public void display () { System.out.println("hello BeanPostProcessor!!!" ); } }
测试方法如下:
ClassPathResource resource = new ClassPathResource ("spring.xml" );DefaultListableBeanFactory factory = new DefaultListableBeanFactory ();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader (factory);reader.loadBeanDefinitions(resource); BeanPostProcessorTest test = (BeanPostProcessorTest) factory.getBean("beanPostProcessorTest" );test.display();
运行结果:
运行结果比较奇怪,为什么没有执行 postProcessBeforeInitialization()
和 postProcessAfterInitialization()
呢?
我们 debug 跟踪下代码,这两个方法在 initializeBean()
方法处调用下,如下:
debug,在 postProcessBeforeInitialization()
方法中结果如下:
这段代码是通过迭代 getBeanPostProcessors()
返回的结果集来调用 postProcessBeforeInitialization()
,但是在这里我们看到该方法返回的结果集为空,所以肯定不会执行相应的 postProcessBeforeInitialization()
方法咯。怎么办?
答案不言而喻:只需要 getBeanPostProcessors()
返回的结果集中存在至少一个元素即可,该方法定义如下:
public List<BeanPostProcessor> getBeanPostProcessors () { return this .beanPostProcessors; }
返回的 beanPostProcessors 是一个 private 的 List ,也就是说只要该类中存在 beanPostProcessors.add()
的调用我们就找到了入口,在类 AbstractBeanFactory 中找到了如下代码:
@Override public void addBeanPostProcessor (BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null" ); this .beanPostProcessors.remove(beanPostProcessor); this .beanPostProcessors.add(beanPostProcessor); if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this .hasInstantiationAwareBeanPostProcessors = true ; } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this .hasDestructionAwareBeanPostProcessors = true ; } }
该方法是由 AbstractBeanFactory 的父类 ConfigurableBeanFactory 定义,它的核心意思就是将指定 BeanPostProcessor 注册到该 BeanFactory 创建的 bean 中,同时它是按照插入的顺序进行注册的,完全忽略 Ordered 接口所表达任何排序语义(在 BeanPostProcessor 中我们提供一个 Ordered 顺序,这个后面讲解)。
到这里应该就比较熟悉了,其实只需要显示调用 addBeanPostProcessor()
就可以了,加入如下代码。
BeanPostProcessorTest beanPostProcessorTest = new BeanPostProcessorTest ();factory.addBeanPostProcessor(beanPostProcessorTest);
运行结果:
其实还有一种更加简单的方法,这个我们后面再说,先看 BeanPostProcessor 的原理。
BeanPostProcessor 基本原理 BeanPostProcessor 接口定义如下:
public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { return bean; } }
BeanPostProcessor 可以理解为是 Spring 的一个工厂钩子(其实 Spring 提供一系列的钩子,如 Aware 、InitializingBean、DisposableBean),它是 Spring 提供的对象实例化阶段强有力的扩展点,允许 Spring 在实例化 bean 阶段对其进行定制化修改,比较常见的使用场景是处理标记接口实现类或者为当前对象提供代理实现(例如AOP)。
一般普通的 BeanFactory 是不支持自动注册 BeanPostProcessor 的,需要我们手动调用 addBeanPostProcessor()
进行注册,注册后的 BeanPostProcessor 适用于所有该 BeanFactory 创建的 bean,但是 ApplicationContext 可以在其 bean 定义中自动检测所有的 BeanPostProcessor 并自动完成注册,同时将他们应用到随后创建的任何 bean 中。
postProcessBeforeInitialization()
和 postProcessAfterInitialization()
两个方法都接收一个 Object 类型的 bean,一个 String 类型的 beanName,其中 bean 是已经实例化了的 instanceBean,能拿到这个你是不是可以对它为所欲为了? 这两个方法是初始化 bean 的前后置处理器,他们应用 invokeInitMethods()
前后。如下图:
代码层次上面已经贴出来,这里再贴一次:
两者源码如下:
@Override public Object applyBeanPostProcessorsBeforeInitialization (Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null ) { return result; } result = current; } return result; } @Override public Object applyBeanPostProcessorsAfterInitialization (Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null ) { return result; } result = current; } return result; }
getBeanPostProcessors()
返回的是 beanPostProcessors 集合,该集合里面存放就是我们自定义的 BeanPostProcessor,如果该集合中存在元素则调用相应的方法,否则就直接返回 bean 了。这也是为什么使用 BeanFactory 容器是无法输出自定义 BeanPostProcessor 里面的内容,因为在 BeanFactory.getBean()
的过程中根本就没有将我们自定义的 BeanPostProcessor 注入进来,所以要想 BeanFactory 容器 的 BeanPostProcessor 生效我们必须手动调用 addBeanPostProcessor()
将定义的 BeanPostProcessor 注册到相应的 BeanFactory 中。但是 ApplicationContext 不需要手动,因为 ApplicationContext 会自动检测并完成注册。
ApplicationContext 实现自动注册的原因在于我们构造一个 ApplicationContext 实例对象的时候会调用 registerBeanPostProcessors()
方法将检测到的 BeanPostProcessor 注入到 ApplicationContext 容器中,同时应用到该容器创建的 bean 中。
protected void registerBeanPostProcessors (ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this ); } public static void registerBeanPostProcessors ( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true , false ); int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate .BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList <>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList <>(); List<String> orderedPostProcessorNames = new ArrayList <>(); List<String> nonOrderedPostProcessorNames = new ArrayList <>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); List<BeanPostProcessor> orderedPostProcessors = new ArrayList <>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors); List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList <>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector (applicationContext)); }
方法首先 beanFactory 获取注册到该 BeanFactory 中所有 BeanPostProcessor 类型的 beanName,其实就是找所有实现了 BeanPostProcessor 接口的 bean ,然后迭代这些 bean,将其按照PriorityOrdered、Ordered、无序的顺序添加至相应的 List 集合中,最后依次调用 sortPostProcessors()
进行排序处理和 registerBeanPostProcessors()
完成注册。排序很简单,如果 beanFactory 为 DefaultListableBeanFactory 则返回 BeanFactory 所依赖的比较器,否则反正默认的比较器(OrderComparator),然后调用 sort()
即可。如下:
private static void sortPostProcessors (List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) { Comparator<Object> comparatorToUse = null ; if (beanFactory instanceof DefaultListableBeanFactory) { comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator(); } if (comparatorToUse == null ) { comparatorToUse = OrderComparator.INSTANCE; } postProcessors.sort(comparatorToUse); }
而对于注册同样是调用 AbstractBeanFactory.addBeanPostProcessor()
方法完成注册,如下:
private static void registerBeanPostProcessors ( ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { for (BeanPostProcessor postProcessor : postProcessors) { beanFactory.addBeanPostProcessor(postProcessor); } }
至此,BeanPostProcessor 已经分析完毕了,这里简单总结下:
BeanPostProcessor 的作用域是容器级别的,它只和所在的容器相关 ,当 BeanPostProcessor 完成注册后,它会应用于所有跟它在同一个容器内的 bean。
BeanFactory 和 ApplicationContext 对 BeanPostProcessor 的处理不同,ApplicationContext 会自动检测所有实现了 BeanPostProcessor 接口的 bean,并完成注册,但是使用 BeanFactory 容器时则需要手动调用 addBeanPostProcessor()
完成注册
ApplicationContext 的 BeanPostProcessor 支持 Ordered,而 BeanFactory 的 BeanPostProcessor 是不支持的,原因在于ApplicationContext 会对 BeanPostProcessor 进行 Ordered 检测并完成排序,而 BeanFactory 中的 BeanPostProcessor 只跟注册的顺序有关。