BeanFactory 继承图
Spring Boot 中 ApplicationContext 的继承图
挺有意思、顶层接口、Configurable、Abstract,然后下面就是比较具体场景的实现类,Environment 也是这样的结构。
- ApplicationContext
- ConfigurableApplicationContext
- AbstractApplicationContext
- GenericApplicationContext
- GenericWebApplicationContext
- ServletWebServerApplicationContext
- AnnotationConfigServletWebServerApplicationContext & XmlServletWebServerApplicationContext
Spring 中 ApplicationContext的继承图
源码分析
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("coderLi.xml"); 复制代码
<bean class="com.demo.data.Cat" id="cat"/> 复制代码
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); } public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } 复制代码
将要放入 Spring 的资源文件也就是 beanDefinition 解释之后赋值给 configLocations 变量保存
public void setConfigLocations(@Nullable String... locations) { if (locations != null) { Assert.noNullElements(locations, "Config locations must not be null"); this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { // 解释给定路径,比如说 路径中包含某些特殊符号 ${var} this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } } protected String resolvePath(String path) { return getEnvironment().resolveRequiredPlaceholders(path); } @Override public ConfigurableEnvironment getEnvironment() { if (this.environment == null) { this.environment = createEnvironment(); } return this.environment; } protected ConfigurableEnvironment createEnvironment() { return new StandardEnvironment(); } 复制代码
resolvePath
会搜寻匹配系统变量并进行替换。关于 Environment 的可以看我另一篇文章:Environment 概述
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } } 复制代码
- prepareRefresh 准备刷新的上下文环境
- obtainFreshBeanFactory 创建 beanfactory 并加载注册 beanDefinition
- prepareBeanFactory 对 beanFactory 各种功能进行填充
- invokeBeanFactoryPostProcessors 对 BeanFactoryPostProcessor的bean 进行回调
- registerBeanPostProcessors 注册 BeanPostProcessors 到 BeanFactory 中
- initMessageSource 国际化
- initApplicationEventMulticaster 创建事件广播器
- onRefresh 空方法、给子类扩展
- registerListeners 注册事件监听器
- finishBeanFactoryInitialization 初始化剩下的单例 非延迟初始化的
- finishRefresh 完成刷新、通知生命周期处理器 lifecycleProcessor 刷新过程、并发布 contextRefreshEvent
- resetCommonCaches 清理使用到的一些内存缓存
prepareRefresh
protected void prepareRefresh() { // ....... // 初始化属性源 initPropertySources(); // 对属性进行验证 getEnvironment().validateRequiredProperties(); } 复制代码
initPropertySources 这个方法默认是空方法、交由子类去扩展。在 GenericWebApplicationContext 中、就将原来放入 Environment 对象中的 Servlet Context 和 Servlet Config 两个属性源占位符进行替换。详细可以看 Environment 概述
@Override protected void initPropertySources() { ConfigurableEnvironment env = getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null); } } 复制代码
obtainFreshBeanFactory
@Override protected final void refreshBeanFactory() throws BeansException { ......... try { // 创建 DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); // 为了序列化的时候、指定 id beanFactory.setSerializationId(getId()); // 定制 beanFactory customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { ..... } } 复制代码
createBeanFactory 去创建 DefaultListableBeanFactory。
customizeBeanFactory 主要去设置两个属性、一个是是否允许 BeanDefinition 覆盖。一个是是否允许循环依赖。
loadBeanDefinitions
将第一步处理好的资源文件路径拿出来进行读取和注册到 BeanDefinitionRegister 中。关于这个部分可以看文章 Spring 容器初始化
prepareBeanFactory
- 设置 BeanClassLoader、默认是获取线程中的 ClassLoader
Thread.currentThread().getContextClassLoader();
- 设置 SPEL 的解释器
- 增加一个属性编辑器的注册点
- 实现 Aware 接口的注入功能。详细可以看以前的文章 Spring Aware 介绍
- 然后就是
ignoreDependencyInterface
相关的、可以看下
registerResolvableDependency
绑定注入类型和对应的 bean- 增加一个 BeanPostProcessor、这个类主要做了一件事就是将 ApplicationListener 对象加入到 ApplicationContext 中保存起来
网络异常,图片无法展示|
往后就是完 BeanFactory 中塞一些对象
所以我们可以通过注解到方式获取对象的对象
postProcessBeanFactory
默认实现方法是空实现、可以在这个方法内对 beanFactory 对一些信息进行修改、这个时机、刚刚好是所有 BeanDefinition 注册完毕、但是没有被实例化。你可以在这个方法中增加 BeanPostProcessor等。
看看其中的一两个子类实现
这个类似于上面的 ApplicationContextAwareProcessor 的功能。
另一个子类、做的事情也是类似的、BootstrapContextAwareProcessor 使用的比较少、有机会再看看吧后续。
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是否是 BeanDefinitionRegistry 、如果是则则判断参数重的 BeanFactoryPostProcessor是否 BeanDefinitionRegistryPostProcessor、如果是则调用 postProcessBeanDefinitionRegistry 方法。
后续则去 BeanFactory中找出对应的 BeanDefinitionRegistryPostProcessor 实例、这其中先是 PriorityOrdered 的、然后是 Ordered 的、最后是正常的。
然后才是去去调用 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法。
最后也是类似的去 beanFactory 中找 BeanFactoryPostProcessor 的实例。这其中先是 PriorityOrdered 的、然后是 Ordered 的、最后是正常的。
流程上不复杂、考虑的情况有点多、所以代码篇幅有点长。
registerBeanPostProcessors
这个方法也是类似的、从 beanFactory 中捞对应的bean 出来注册然后注册、顺序 方面也是 PriorityOrdered然后Ordered、然后正常。里面也涉及到了对 MergedBeanDefinitionPostProcessor 的注册、其实它是 BeanPostProcessor的子类。
initMessageSource
初始化消息资源、国际化相关的,不太熟悉
protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { hms.setParentMessageSource(getInternalParentMessageSource()); } } } else { DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); } } 复制代码
initApplicationEventMulticaster
注册一个事件广播器、这个也没啥说的
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); } } 复制代码
onRefresh
模版方法、给子类去扩展的方法。
registerListeners
注册监听器
protected void registerListeners() { for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } } 复制代码
finishBeanFactoryInitialization
这个方法主要去初始化剩下非延迟初始化的 bean。 涉及到 ConversionService 、以及冻结 BeanDefinition、最后去调用 BeanFactory 的 preInstantiationSingletons方法 这个方法主要是获取所有的 BeanDefinition 然后调用 getBean 方法去实例化。如果是 FactoryBean 则会根据是否是 eager 去判断是否获取实际的 Bean。 最后会去对实现了 SmartInitializingSingleton 的回调接口。
finishRefresh
- 清理 Resource 资源
- 初始化 LifecycleProcessor
- 调用 LifecycleProcessor 的 on Refresh 方法
- 发布 ContextRefreshEvent
resetCommonCaches
这个方法在 finally 代码块中。主要是清理各种缓存资源,比如说 Spring 自定义了一个 Introspector 的检查。还有各种的其他缓存。
总结
其实整一个 refresh 过程还是挺简单的、从大体上来看、与我们直接使用 BeanFactory 的时候相比、多了一些扩展性的东西、但是这些扩展的地方、都是原本Spring 提供给我们、我们自己也可以进行扩展的。