Spring源码学习笔记(3)——容器的功能扩展
一. 引入ApplicationContext接口
-
前面的介绍都是基于BeanFactory接口和它的默认实现XmlBeanFactory的,但是Spring体系中还有一个重要的接口:ApplicationContext。ApplicationContext在BeanFactory上进行了一些扩展,功能更为强大。可以理解为:BeanFactory是Spring容器内部使用的,而ApplicationContext是暴露给应用使用的。除非在一些特殊情况下,否则Spring建议使用ApplicationContext接口的实现类。
-
示例程序
以一段几乎每个Java程序员都写过的代码为例:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");ClassPathXmlApplicationContext可以支持多个配置路径,在setConfigLocations()方法中进行处理,后续功能都在refresh()方法中:
public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); //设置配置路径 setConfigLocations(configLocations); if (refresh) { refresh(); } }下面重点分析refresh()方法。
二. 整体流程
-
refresh()的实现在AbstractApplicationContext类中,这是ApplicationContext体系中十分重要的一个方法,在整体上定义了ApplicationContext容器的启动流程:
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //准备带刷新的上下文环境 prepareRefresh(); //初始化BeanFactory,并读取Spring配置文件 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //对初始化BeanFactory进行各种功能的填充 prepareBeanFactory(beanFactory); try { //提供给子类的模板方法,可做额外处理 postProcessBeanFactory(beanFactory); //激活容器中注册的处理器,进行各种处理 invokeBeanFactoryPostProcessors(beanFactory); //注册BeanPosyProcesor后处理器,拦截Bean的创建过程。这里只是注册,并未执行 registerBeanPostProcessors(beanFactory); //为容器初始化各种Message源,即多语言、国际化处理 initMessageSource(); //初始化消息广播器,将applicationEventMulticaster注册到单例容器中,为容器的消息机制做准备 initApplicationEventMulticaster(); //提供给子类的模板方法,可初始化其他Bean onRefresh(); //在所有注册的Bean中查找Listener Bean,注册到消息广播器applicationEventMulticaster中 registerListeners(); //初始化剩余的单例Bean(非lazy-init的) finishBeanFactoryInitialization(beanFactory); //最后一步:完成容器刷新过程,通知容器中的LifecycleProcessor刷新完成,并且发布ContextRefreshedEvent容器刷新完成事件 finishRefresh(); } //异常处理 catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { //清空Spring通用缓存 resetCommonCaches(); } } } -
可以看到,整个refresh()的流程是很清晰的,处理异常处理外,大概做了这么几件事:
-
初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。
在某些情况下,项目的运行需要读取某些系统变量,这些变量的设置可能会影响系统的正确性,此时prepareRefresh()这个方法就可以发挥它的作用,在容器启动时(一般也是项目启动时)为我们检查这些变量的设置。
-
初始化BeanFactory,并读取XML配置文件
在这一步中会复用BeanFactory的读取配置文件和加载Bean的过程,在这一步之后,ApplicationContext实际上就包含了所有BeanFactory所提供的功能,可以进行Bean的提取等工作了。
-
对BeanFactory进行各种功能的填充
-
提供给子类模板方法,做额外的扩展
-
激活各种FactoryBean进行处理
-
注册BeanPostProcessor后处理器,这里只是注册,真正调用是在getBean()时
-
为上下文初始化Message源,处理多语言和国际化
-
初始化应用消息广播器ApplicationEventMulticaster,为Spring消息机制做准备
-
提供给子类模板方法,初始化其他的Bean
-
在所有注册的Bean中查找ApplicationListener,注册到ApplicationEventMulticaster
-
初始化其余的非延迟加载的单实例Bean
-
完成容器刷新过程,通知LifecycleProcessor,并发布ContextRefreshedEvent容器刷新完成事件
-
-
下面仔细分析具体每一步的处理逻辑
三. 环境准备
-
查看方法实现:
protected void prepareRefresh() { this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } //初始化placeholder属性源,默认空实现,留给子类覆盖 initPropertySources(); //校验所有需要的属性文件是否都已经放入环境中 getEnvironment().validateRequiredProperties(); //为early的容器事件做准备 this.earlyApplicationEvents = new LinkedHashSet<>(); } -
这个方法的核心逻辑默认都是空实现,可以交给子类去覆盖,例如我们可以自定义一个ApplicationContext,并且校验自己的属性文件和系统变量配置
四. 加载BeanFactory
-
前面说过,ApplicationContext是对BeanFactory功能上的扩展,不但包含了BeanFactory的全部功能,更是在其基础上添加了大量的扩展应用,obtainFreshBeanFactory()正是实现了BeanFactory的地方,在这个方法之后,ApplicationContext方法就拥有了BeanFactory的全部功能。代码实现:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //初始化BeanFactory,并进行XML文件读取,而且将得到的BeanFactory记录在当前实体的属性中 refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }核心逻辑委托给了AbstractRefreshableApplicationContext的refreshBeanFactory()方法实现:
protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //创建DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); //指定序列化id,如果需要的话,可以根据序列化id反序列化出BeanFactory对象 beanFactory.setSerializationId(getId()); //定制BeanFactory相关属性, customizeBeanFactory(beanFactory); //初始化DocumentReader,进行配置文件的读取和解析 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } -
refreshBeanFactory()的具体步骤:
-
创建DefaultListableBeanFactory
DefaultListableBeanFactory是比较基础的BeanFactory类型。
-
设置序列化id。
-
定制BeanFactory,是对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖和是否允许循环引用的支持。
-
读取配置文件,加载BeanDefinition,该方法交给子类重写,如AbstractXmlApplicationContext类中实现了读取XML文件加载BeanDefinition的处理。
-
使用全局变量beanFactory记录BeanFactory实例
-
五. 对初始化好的BeanFactory进行各种功能的填充
-
对于上面初始化好的BeanFactory,进行一些属性的设置和功能上的扩展,具体逻辑在prepareBeanFactory()中:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //设置BeanFactory的ClassLoader为当前ApplicationContext的ClassLoader beanFactory.setBeanClassLoader(getClassLoader()); //设置BeanFactory的表达式语言处理器,支持表达式语言 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //为BeanFactory设置一个默认的PropertyEditor,这个主要是对Bean的属性等设置管理的一个工具 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); //添加后处理器 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //设置几个忽略自动装配的接口 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //设置几个自动装配的特殊规则 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //增加AspectJ的支持 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //注册默认的系统Bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } } -
该方法主要对BeanFactory进行了以下几个方面的扩展:
- 对SPEL表达式的支持
- 对属性编辑器的支持
- 增加对一些内置类,如EnvironmentAware、MessageSourceAware的信息注入
- 对AspectJ的支持
六. BeanFactory的后处理
-
BeanFactoryPostProcessor
在BeanFactory的定制化完成之后,开始执行BeanFactory的后处理,后处理主要依赖BeanFactoryPostProcessor类进行。BeanFactoryPostProcessor的功能类似于BeanPostProcessor,可以对Bean的定义(配置元数据)进行处理,也就是说,Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何其他的Bean之前读取配置元数据,并可能修改它。BeanFactoryPostProcessor与BeanPostProcessor的主要区别在于,BeanFactoryPostProcessor是容器级别的,它的处理依赖于当前的BeanFactory,而且不要通过BeanFactoryPostProcessor进行Bean实例化的相关处理,BeanFactoryPostProcessor只能处理BeanDifinition。
-
激活BeanFactoryPostProcessor
下面回到refresh()方法的处理,调用invokeBeanFactoryPostProcessors()激活容器中注册的BeanFactoryPostProcessor:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }核心方法为PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()),调用容器中所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。
七. 注册BeanPostProcessor
-
ApplicationContext在registerBeanPostProcessors()方法中注册了BeanPostProcessor,这里只是注册,并不是调用,真正的调用实在创建Bean的时候处理的。这是一个重要的步骤,也是BeanFactory不支持BeanPostProcessor的原因:BeanFactory中没有实现后处理器的自动注册,只能手动注册。
-
具体实现:
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { //获取所有BeanPostProcessor的Bean Name String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); //向容器中注册BeanPostProcessorChecker后处理器,只是一个普通的打印 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); //使用priorityOrderedPostProcessors保证顺序 List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); //使用orderedPostProcessorNames保证顺序 List<String> orderedPostProcessorNames = new ArrayList<>(); //无序的BeanPostProcessors 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); } } //1.排序,注册所有实现了PriorityOrdered接口的有序BeanPostProcessor sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); //2.排序,注册所有实现了Ordered接口的有序BeanPostProcessor 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); //3.注册无序的BeanPostProcessor 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); //最后,注册实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, internalPostProcessors); //注册ApplicationListenerDetector探测器 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
八. 后续步骤
-
初始化消息资源
-
初始化ApplicationEventMulticaster,为Spring的Event体系提供支持。
当发布容器事件时,会默认使用SimpleApplicationEventMulticaster对事件进行广播,遍历所有的ApplicationListener,回调ApplicationListener的onApplicationEvent()方法处理事件。每个监听器都可以监听到容器发布的所有事件,但是是否处理由监听器逻辑决定。
-
注册监听器
上面提到的Event体系中的监听器,就是在这里注册的。
-
初始化非延迟加载的单例Bean
-
容器刷新完成