Spring源码阅读-开闭原则
2017-02-04 00:00
417 查看
前言
问题引入:对大型系统的某个功能进行修改,如果直接修改代码可能会引入其他未知bug,并且需要了解整个系统的人才能重构修改,而且需要重新完整测试,这就严重约束了系统的扩展性。遵守开闭原则就能很好的解决上面问题,开闭原则的定义为:软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的(概念参考wiki),也就是说在不修改旧代码的前提下加入新功能。
这种概念第一种最直接的实现方式就是重新实现上层接口,根据特定的场景生成一个特定的子类,第二种实现方式就是继承某个类,这样只需要修改一部分代码,可以让自定义子类重新实现的代码块最小化,这在spring中处处有体现,从ApplicationContext和BeanFactory的繁多的子类就可以看出不同场景都有各种的实现类,上篇AbstractApplicationContext的加载就也可以看出来,有部分方法是空的就是留给子类实现的。
除上面之外,用户可能只想在不改变方法逻辑的情况下对某个对象进行自定义干预,如果重新实现整个方法也不妥,所以spring还在初始化的各个环节中埋入了BeanPostProcessor或BeanFactoryPostProcessor接口,只需要实现该接口即可以在某个点位干预初对象,这也是spring容器的扩展点。
spring容器的扩展点
看名字就能猜出:BeanPostProcessor是对bean创建的干预,BeanFactoryPostProcessor是对bean工厂的干预,还是实际验证为主:BeanFactoryPostProcessor
1. 先看一下BeanFactoryPostProcessor的方法参数(这个通常是干预的对象),该接口只有一个方法:void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
看方法参数为beanFactory,所以该方法里面可以对bean工厂做任何事。
2. 再看被调用的地方:
![](https://static.oschina.net/uploads/space/2017/0204/095500_LEAq_1445156.png)
这个比较简单,就在AbstractApplicationContext的refresh方法中用到,在前篇中有说到refresh方法,在beanFactory初始化完毕调用invokeBeanFactoryPostProcessors来做一些完善工作,最终委托给PostProcessorRegistrationDelegate在对象实例化之前执行所有注册的BeanFactoryPostProcessors,代码如下:
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<String>(); // 如果继承BeanDefinitionRegistry接口, 优先执行BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; //存放普通的 List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); //存放注册型的 List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); for (BeanFactoryPo 3ff8 stProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; //直接执行postProcessBeanDefinitionRegistry registryPostProcessor.postProcessBeanDefinitionRegistry(registry); registryPostProcessors.add(registryPostProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement PriorityOrdered, Ordered, and the rest. //获取beanFactory中BeanDefinitionRegistryPostProcessor类型的bean String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // 下面按优先级排序执行 // 先获取实现了PriorityOrdered接口的 // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //postProcessor有执行先后顺序,会实现一个接口PriorityOrdered OrderComparator.sort(priorityOrderedPostProcessors); registryPostProcessors.addAll(priorityOrderedPostProcessors); //执行postProcessBeanDefinitionRegistry invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); //再获取实现了Ordered接口的 // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } OrderComparator.sort(orderedPostProcessors); registryPostProcessors.addAll(orderedPostProcessors); //执行postProcessBeanDefinitionRegistry invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry); //最后执行其他的 // 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)) { BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class); registryPostProcessors.add(pp); processedBeans.add(ppName); pp.postProcessBeanDefinitionRegistry(registry); reiterate = true; } } } // 最后执行postProcessBeanFactory方法 // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } //下面以同样的方法分步获取BeanFactoryPostProcessor执行 // 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<BeanFactoryPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); 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); } } // 根据优先级顺序分别执行postProcessBeanFactory // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. OrderComparator.sort(priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } OrderComparator.sort(orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); }
上面代码很长,但实际上就做了一件事,根据优先级不同,接口类型不同来分别执行不同方法,如下顺序:
执行对象优先级:传过来的方法参数对象、实现接口PriorityOrdered、 Ordered、其他
执行方法优先级:如果beanFactory继承自BeanDefinitionRegistry接口,则优先执行BeanDefinitionRegistryPostProcessor子接口的postProcessBeanDefinitionRegistry方法,并且遵守第一条。
执行相同方法不同接口的优先级:执行postProcessBeanFactory方法,优先执行BeanDefinitionRegistryPostProcessor子类的,其次执行BeanFactoryPostProcessor子类的,并同时遵守第一条
BeanPostProcessor
1. 它的方法参数为bean,可以看看这种接口的扩展点是对对象就行干预的。2. 看看BeanPostProcessor被调用的位置,基本在createBean的每个过程中都有埋点,并且也分了好几种类型,在不同流程调用不同子接口,
看看AbstractAutowireCapableBeanFactory创建对象调用BeanPostProcessor流程:
![](https://static.oschina.net/uploads/space/2017/0204/112439_iiev_1445156.png)
可以看出在每个关键点位都有埋点,并且又根据不同功能区分了几个子接口,具体的接口及其子类功能后篇在看。
3. BeanPostProcessor被注册的地方:在AbstractApplicationContext的refresh方法中执行完BeanFactoryPostProcessors就调用registerBeanPostProcessors方法注册BeanPostProcessor,也是最终委托给PostProcessorRegistrationDelegate进行注册,这里注册跟上面BeanFactoryPostProcessor的执行是一个原理,按照一定的优先级排序:实现接口PriorityOrdered、Ordered、其他,最后注册实现MergedBeanDefinitionPostProcessor接口的对象。
总结
到这里只是大体看了扩展点在容器中是怎么注册,怎么调用的,具体各种类型的扩展点还要后续再看。相关文章推荐
- Spring 源码阅读之BeanFactory
- Spring工具类的源码阅读(更新中~)
- Spring源码阅读——BeanFactory体系结构
- Spring源码阅读入门指引
- Spring 源码阅读 一
- spring源码下载及与myeclipse集成阅读
- Spring源码阅读--AbstractApplicationContext refresh()方法调用
- spring-mvc源码阅读(三)RequestMappingHandlerMapping
- spring-mvc源码阅读(二)<mvc:annotation-driven/>做了什么
- Spring源码阅读:IOC容器的设计与实现(二)——ApplicationContext
- Spring IOC 源码阅读资源加载和注册
- 初始化IoC容器(Spring源码阅读)
- 初始化IoC容器(Spring源码阅读)-我们到底能走多远系列(31)
- Spring源码阅读——获得bean
- Spring 源码阅读(二)——Spring的初始化以及资源加载
- Spring IoC容器在Web环境中的启动源码阅读
- Spring源码阅读之IoC容器初始化3 -- BeanDefinition在IoC容器中的注册
- Spring源码阅读1---导入eclipse
- Spring源码阅读笔记(待补充)
- Spring源码阅读系列总结