Spring源码剖析3懒加载的单例Bean获取过程分析

24次阅读

共计 43068 个字符,预计需要花费 108 分钟才能阅读完成。


转自【Spring 源码分析】Bean 加载流程概览

代码入口

之前写文章都会啰啰嗦嗦一大堆再开始,进入【Spring 源码分析】这个板块就直接切入正题了。

很多朋友可能想看 Spring 源码,但是不知道应当如何入手去看,这个可以理解:Java 开发者通常从事的都是 Java Web 的工作,对于程序员来说,一个 Web 项目用到 Spring,只是配置一下配置文件而已,Spring 的加载过程相对是不太透明的,不太好去找加载的代码入口。

下面有很简单的一段代码可以作为 Spring 代码加载的入口:

<pre> 1 ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);
2 ac.getBean(XXX.class);</pre>

ClassPathXmlApplicationContext 用于加载 CLASSPATH 下的 Spring 配置文件,可以看到,第二行就已经可以获取到 Bean 的实例了,那么必然第一行就已经完成了对所有 Bean 实例的加载,因此可以通过 ClassPathXmlApplicationContext 作为入口。为了后面便于代码阅读,先给出一下 ClassPathXmlApplicationContext 这个类的继承关系:

大致的继承关系是如上图所示的,由于版面的关系,没有继续画下去了,左下角的 ApplicationContext 应当还有一层继承关系,比较关键的一点是它是 BeanFactory 的子接口。

最后声明一下,本文使用的 Spring 版本为 3.0.7,比较老,使用这个版本纯粹是因为公司使用而已。

ClassPathXmlApplicationContext 存储内容

为了更理解 ApplicationContext,拿一个实例 ClassPathXmlApplicationContext 举例,看一下里面存储的内容,加深对 ApplicationContext 的认识,以表格形式展现:

对象名 类 型 作 用 归属类
configResourcesResource[] 配置文件资源对象数组 ClassPathXmlApplicationContext
configLocationsString[] 配置文件字符串数组,存储配置文件路径 AbstractRefreshableConfigApplicationContext
beanFactoryDefaultListableBeanFactory 上下文使用的 Bean 工厂 AbstractRefreshableApplicationContext
beanFactoryMonitorObjectBean 工厂使用的同步监视器 AbstractRefreshableApplicationContext
idString 上下文使用的唯一 Id,标识此 ApplicationContextAbstractApplicationContext
parentApplicationContext 父级 ApplicationContextAbstractApplicationContext
beanFactoryPostProcessorsList<BeanFactoryPostProcessor> 存储 BeanFactoryPostProcessor 接口,Spring 提供的一个扩展点 AbstractApplicationContext
startupShutdownMonitorObjectrefresh 方法和 destory 方法公用的一个监视器,避免两个方法同时执行 AbstractApplicationContext
shutdownHookThreadSpring 提供的一个钩子,JVM 停止执行时会运行 Thread 里面的方法 AbstractApplicationContext
resourcePatternResolverResourcePatternResolver 上下文使用的资源格式解析器 AbstractApplicationContext
lifecycleProcessorLifecycleProcessor 用于管理 Bean 生命周期的生命周期处理器接口 AbstractApplicationContext
messageSourceMessageSource 用于实现国际化的一个接口 AbstractApplicationContext
applicationEventMulticasterApplicationEventMulticasterSpring 提供的事件管理机制中的事件多播器接口 AbstractApplicationContext
applicationListenersSet<ApplicationListener>Spring 提供的事件管理机制中的应用监听器 AbstractApplicationContext

ClassPathXmlApplicationContext 构造函数

看下 ClassPathXmlApplicationContext 的构造函数:

<pre> 1 public ClassPathXmlApplicationContext(String configLocation) throws BeansException {2 this(new String[] {configLocation}, true, null);
3 }</pre>

<pre>1 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) 2 throws BeansException {3
4 super(parent); 5 setConfigLocations(configLocations); 6 if (refresh) {7 refresh(); 8 } 9 }</pre>

从第二段代码看,总共就做了三件事:

1、super(parent)

没什么太大的作用,设置一下父级 ApplicationContext,这里是 null

2、setConfigLocations(configLocations)

代码就不贴了,一看就知道,里面做了两件事情:

(1)将指定的 Spring 配置文件的路径存储到本地

(2)解析 Spring 配置文件路径中的 ${PlaceHolder} 占位符,替换为系统变量中 PlaceHolder 对应的 Value 值,System 本身就自带一些系统变量比如 class.path、os.name、user.dir 等,也可以通过 System.setProperty() 方法设置自己需要的系统变量

refresh()

这个就是整个 Spring Bean 加载的核心了,它是 ClassPathXmlApplicationContext 的父类 AbstractApplicationContext 的一个方法,顾名思义,用于刷新整个 Spring 上下文信息,定义了整个 Spring 上下文加载的流程。

refresh 方法

上面已经说了,refresh() 方法是整个 Spring Bean 加载的核心,因此看一下整个 refresh() 方法的定义:

<pre> 1 public void refresh() throws BeansException, IllegalStateException { 2 synchronized (this.startupShutdownMonitor) {
3 // Prepare this context for refreshing.
4 prepareRefresh();
5
6 // Tell the subclass to refresh the internal bean factory.
7 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 8
9 // Prepare the bean factory for use in this context.
10 prepareBeanFactory(beanFactory); 11
12 try {13 // Allows post-processing of the bean factory in context subclasses.
14 postProcessBeanFactory(beanFactory); 15
16 // Invoke factory processors registered as beans in the context.
17 invokeBeanFactoryPostProcessors(beanFactory); 18
19 // Register bean processors that intercept bean creation.
20 registerBeanPostProcessors(beanFactory); 21
22 // Initialize message source for this context.
23 initMessageSource(); 24
25 // Initialize event multicaster for this context.
26 initApplicationEventMulticaster(); 27
28 // Initialize other special beans in specific context subclasses.
29 onRefresh(); 30
31 // Check for listener beans and register them.
32 registerListeners(); 33
34 // Instantiate all remaining (non-lazy-init) singletons.
35 finishBeanFactoryInitialization(beanFactory); 36
37 // Last step: publish corresponding event.
38 finishRefresh(); 39} 40
41 catch (BeansException ex) {42 // Destroy already created singletons to avoid dangling resources.
43 destroyBeans(); 44
45 // Reset ‘active’ flag.
46 cancelRefresh(ex); 47
48 // Propagate exception to caller.
49 throw ex; 50 } 51 } 52 }</pre>

每个子方法的功能之后一点一点再分析,首先 refresh() 方法有几点是值得我们学习的:

1、方法是加锁的,这么做的原因是避免多线程同时刷新 Spring 上下文

2、尽管加锁可以看到是针对整个方法体的,但是没有在方法前加 synchronized 关键字,而使用了对象锁 startUpShutdownMonitor,这样做有两个好处:

(1)refresh() 方法和 close() 方法都使用了 startUpShutdownMonitor 对象锁加锁,这就保证了在调用 refresh() 方法的时候无法调用 close() 方法,反之亦然,避免了冲突

(2)另外一个好处不在这个方法中体现,但是提一下,使用对象锁可以减小了同步的范围,只对不能并发的代码块进行加锁,提高了整体代码运行的效率

3、方法里面使用了每个子方法定义了整个 refresh() 方法的流程,使得整个方法流程清晰易懂。这点是非常值得学习的,一个方法里面几十行甚至上百行代码写在一起,在我看来会有三个显著的问题:

(1)扩展性降低。反过来讲,假使把流程定义为方法,子类可以继承父类,可以根据需要重写方法

(2)代码可读性差。很简单的道理,看代码的人是愿意看一段 500 行的代码,还是愿意看 10 段 50 行的代码?

(3)代码可维护性差。这点和上面的类似但又有不同,可维护性差的意思是,一段几百行的代码,功能点不明确,不易后人修改,可能会导致“牵一发而动全身”

prepareRefresh 方法

下面挨个看 refresh 方法中的子方法,首先是 prepareRefresh 方法,看一下源码:

<pre> 1 /**
2 * Prepare this context for refreshing, setting its startup date and
3 * active flag.
4 */
5 protected void prepareRefresh() { 6 this.startupDate = System.currentTimeMillis(); 7 synchronized (this.activeMonitor) {
8 this.active = true;
9 } 10
11 if (logger.isInfoEnabled()) {12 logger.info(“Refreshing ” + this); 13 } 14 }</pre>

这个方法功能比较简单,顾名思义,准备刷新 Spring 上下文,其功能注释上写了:

1、设置一下刷新 Spring 上下文的开始时间

2、将 active 标识位设置为 true

另外可以注意一下 12 行这句日志,这句日志打印了真正加载 Spring 上下文的 Java 类。

obtainFreshBeanFactory 方法

obtainFreshBeanFactory 方法的作用是获取刷新 Spring 上下文的 Bean 工厂,其代码实现为:

<pre>1 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 2 refreshBeanFactory(); 3 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 4 if (logger.isDebugEnabled()) {5 logger.debug(“Bean factory for ” + getDisplayName() + “: ” + beanFactory); 6 } 7 return beanFactory; 8 }</pre>

其核心是第二行的 refreshBeanFactory 方法,这是一个抽象方法,有 AbstractRefreshableApplicationContext 和 GenericApplicationContext 这两个子类实现了这个方法,看一下上面 ClassPathXmlApplicationContext 的继承关系图即知,调用的应当是 AbstractRefreshableApplicationContext 中实现的 refreshBeanFactory,其源码为:

<pre> 1 protected final void refreshBeanFactory() throws BeansException { 2 if (hasBeanFactory()) {3 destroyBeans();
4 closeBeanFactory();
5 }
6 try {7 DefaultListableBeanFactory beanFactory = createBeanFactory(); 8 beanFactory.setSerializationId(getId());
9 customizeBeanFactory(beanFactory); 10 loadBeanDefinitions(beanFactory); 11 synchronized (this.beanFactoryMonitor) {12 this.beanFactory = beanFactory; 13} 14 } 15 catch (IOException ex) {16 throw new ApplicationContextException(“I/O error parsing bean definition source for ” + getDisplayName(), ex); 17 } 18 }</pre>

这段代码的核心是第 7 行,这行点出了 DefaultListableBeanFactory 这个类,这个类是构造 Bean 的核心类,这个类的功能会在下一篇文章中详细解读,首先给出 DefaultListableBeanFactory 的继承关系图:

AbstractAutowireCapableBeanFactory 这个类的继承层次比较深,版面有限,就没有继续画下去了,本图基本上清楚地展示了 DefaultListableBeanFactory 的层次结构。

为了更清晰地说明 DefaultListableBeanFactory 的作用,列举一下 DefaultListableBeanFactory 中存储的一些重要对象及对象中的内容,DefaultListableBeanFactory 基本就是操作这些对象,以表格形式说明:

对象名 类 型 作 用 归属类
aliasMapMap<String, String> 存储 Bean 名称 ->Bean 别名映射关系 SimpleAliasRegistry
singletonObjectsMap<String, Object> 存储单例 Bean 名称 -> 单例 Bean 实现映射关系 DefaultSingletonBeanRegistry
singletonFactoriesMap<String, ObjectFactory> 存储 Bean 名称 ->ObjectFactory 实现映射关系 DefaultSingletonBeanRegistry
earlySingletonObjectsMap<String, Object> 存储 Bean 名称 -> 预加载 Bean 实现映射关系 DefaultSingletonBeanRegistry
registeredSingletonsSet<String> 存储注册过的 Bean 名 DefaultSingletonBeanRegistry
singletonsCurrentlyInCreationSet<String> 存储当前正在创建的 Bean 名 DefaultSingletonBeanRegistry
disposableBeansMap<String, Object> 存储 Bean 名称 ->Disposable 接口实现 Bean 实现映射关系 DefaultSingletonBeanRegistry
factoryBeanObjectCacheMap<String, Object> 存储 Bean 名称 ->FactoryBean 接口 Bean 实现映射关系 FactoryBeanRegistrySupport
propertyEditorRegistrarsSet<PropertyEditorRegistrar> 存储 PropertyEditorRegistrar 接口实现集合 AbstractBeanFactory
embeddedValueResolversList<StringValueResolver> 存储 StringValueResolver(字符串解析器)接口实现列表 AbstractBeanFactory
beanPostProcessorsList<BeanPostProcessor> 存储 BeanPostProcessor 接口实现列表 AbstractBeanFactory
mergedBeanDefinitionsMap<String, RootBeanDefinition> 存储 Bean 名称 -> 合并过的根 Bean 定义映射关系 AbstractBeanFactory
alreadyCreatedSet<String> 存储至少被创建过一次的 Bean 名集合 AbstractBeanFactory
ignoredDependencyInterfacesSet<Class> 存储不自动装配的接口 Class 对象集合 AbstractAutowireCapableBeanFactory
resolvableDependenciesMap<Class, Object> 存储修正过的依赖映射关系 DefaultListableBeanFactory
beanDefinitionMapMap<String, BeanDefinition> 存储 Bean 名称 –>Bean 定义映射关系 DefaultListableBeanFactory
beanDefinitionNamesList<String> 存储 Bean 定义名称列表 DefaultListableBeanFactory

==================================================================================

Spring 是如何初始化 Bean 实例对象

代码入口

上文【Spring 源码分析】Bean 加载流程概览,比较详细地分析了 Spring 上下文加载的代码入口,并且在 AbstractApplicationContext 的 refresh 方法中,点出了 finishBeanFactoryInitialization 方法完成了对于所有非懒加载的 Bean 的初始化。

finishBeanFactoryInitialization 方法中调用了 DefaultListableBeanFactory 的 preInstantiateSingletons 方法,本文针对 preInstantiateSingletons 进行分析,解读一下 Spring 是如何初始化 Bean 实例对象出来的。

DefaultListableBeanFactory 的 preInstantiateSingletons 方法

DefaultListableBeanFactory 的 preInstantiateSingletons 方法,顾名思义,初始化所有的单例 Bean,看一下方法的定义:

<pre> 1 public void preInstantiateSingletons() throws BeansException { 2 if (this.logger.isInfoEnabled()) {
3 this.logger.info(“Pre-instantiating singletons in ” + this);
4 }
5 synchronized (this.beanDefinitionMap) {
6 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 7 // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
8 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
9 for (String beanName : beanNames) {10 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 11 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {12 if (isFactoryBean(beanName)) {13 final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName); 14 boolean isEagerInit; 15 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {16 isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {17 public Boolean run() {18 return ((SmartFactoryBean) factory).isEagerInit(); 19} 20 }, getAccessControlContext()); 21 } 22 else {23 isEagerInit = (factory instanceof SmartFactoryBean &&
24 ((SmartFactoryBean) factory).isEagerInit()); 25 } 26 if (isEagerInit) {27 getBean(beanName); 28 } 29 } 30 else {31 getBean(beanName); 32 } 33 } 34 } 35 } 36 }</pre>

这里先解释一下 getMergedLocalBeanDefinition 方法的含义,因为这个方法会常常看到。Bean 定义公共的抽象类是 AbstractBeanDefinition,普通的 Bean 在 Spring 加载 Bean 定义的时候,实例化出来的是 GenericBeanDefinition,而 Spring 上下文包括实例化所有 Bean 用的 AbstractBeanDefinition 是 RootBeanDefinition,这时候就使用 getMergedLocalBeanDefinition 方法做了一次转化,将非 RootBeanDefinition 转换为 RootBeanDefinition 以供后续操作。

解释完了 getMergedLocalBeanDefinition 方法的作用,第 1 行~ 第 10 行的代码就没什么好说的了,根据 beanName 拿到 RootBeanDefinition 而已。由于此方法实例化的是所有非懒加载的单例 Bean,因此要实例化 Bean,必须满足 11 行的三个定义:

(1)不是抽象的

(2)必须是单例的

(3)必须是非懒加载的

接着简单看一下第 12 行~ 第 29 行的代码,这段代码主要做的是一件事情:首先判断一下 Bean 是否 FactoryBean 的实现,接着判断 Bean 是否 SmartFactoryBean 的实现,假如 Bean 是 SmartFactoryBean 的实现并且 eagerInit(这个单词字面意思是渴望加载,找不到一个好的词语去翻译,意思就是定义了这个 Bean 需要立即加载的意思)的话,会立即实例化这个 Bean。Java 开发人员不需要关注这段代码,因为 SmartFactoryBean 基本不会用到,我翻译一下 Spring 官网对于 SmartFactoryBean 的定义描述:

  • FactoryBean 接口的扩展接口。接口实现并不表示是否总是返回单独的实例对象,比如 FactoryBean.isSingleton() 实现返回 false 的情况并不清晰地表示每次返回的都是单独的实例对象
  • 不实现这个扩展接口的简单 FactoryBean 的实现,FactoryBean.isSingleton() 实现返回 false 总是简单地告诉我们每次返回的都是单独的实例对象,暴露出来的对象只能够通过命令访问
  • 注意:这个接口是一个有特殊用途的接口,主要用于框架内部使用与 Spring 相关。通常,应用提供的 FactoryBean 接口实现应当只需要实现简单的 FactoryBean 接口即可,新方法应当加入到扩展接口中去

代码示例

为了后面的代码分析方便,事先我定义一个 Bean:

<pre> 1 package org.xrq.action; 2
3 import org.springframework.beans.factory.BeanClassLoaderAware; 4 import org.springframework.beans.factory.BeanNameAware; 5 import org.springframework.beans.factory.InitializingBean; 6
7 public class MultiFunctionBean implements InitializingBean, BeanNameAware, BeanClassLoaderAware {8
9 private int propertyA; 10
11 private int propertyB; 12
13 public int getPropertyA() { 14 return propertyA; 15} 16
17 public void setPropertyA(int propertyA) {18 this.propertyA = propertyA; 19} 20
21 public int getPropertyB() { 22 return propertyB; 23} 24
25 public void setPropertyB(int propertyB) {26 this.propertyB = propertyB; 27} 28
29 public void initMethod() { 30 System.out.println(“Enter MultiFunctionBean.initMethod()”); 31 } 32
33 @Override 34 public void setBeanClassLoader(ClassLoader classLoader) {35 System.out.println(“Enter MultiFunctionBean.setBeanClassLoader(ClassLoader classLoader)”); 36 } 37
38 @Override 39 public void setBeanName(String name) {40 System.out.println(“Enter MultiFunctionBean.setBeanName(String name)”); 41 } 42
43 @Override 44 public void afterPropertiesSet() throws Exception { 45 System.out.println(“Enter MultiFunctionBean.afterPropertiesSet()”); 46 } 47
48 @Override 49 public String toString() { 50 return “MultiFunctionBean [propertyA=” + propertyA + “, propertyB=” + propertyB + “]”; 51 } 52
53 }</pre>

定义对应的 spring.xml:

<pre>1 <?xml version=”1.0″ encoding=”UTF-8″?>
2 <beans xmlns=”http://www.springframework.org/schema/beans”
3 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
4 xsi:schemaLocation=”http://www.springframework.org/schema/beans 5 http://www.springframework.or…d”>
6
7 <bean id=”multiFunctionBean” class=”org.xrq.action.MultiFunctionBean” init-method=”initMethod” />
8
9 </beans></pre>

利用这个 MultiFunctionBean,我们可以用来探究 Spring 加载 Bean 的多种机制。

doGetBean 方法构造 Bean 流程

上面把 getBean 之外的代码都分析了一下,看代码就可以知道,获取 Bean 对象实例,都是通过 getBean 方法,getBean 方法最终调用的是 DefaultListableBeanFactory 的父类 AbstractBeanFactory 类的 doGetBean 方法,因此这部分重点分析一下 doGetBean 方法是如何构造出一个单例的 Bean 的。

doGetBean 方法是如何构造出一个单例的 Bean

看一下 doGetBean 方法的代码实现,比较长:

<pre> 1 protected <T> T doGetBean(2 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) 3 throws BeansException {4
5 final String beanName = transformedBeanName(name); 6 Object bean;
7
8 // Eagerly check singleton cache for manually registered singletons.
9 Object sharedInstance = getSingleton(beanName); 10 if (sharedInstance != null && args == null) {
11 if (logger.isDebugEnabled()) {12 if (isSingletonCurrentlyInCreation(beanName)) {13 logger.debug(“Returning eagerly cached instance of singleton bean ‘” + beanName +
14 “‘ that is not fully initialized yet – a consequence of a circular reference”);
15 }
16 else {17 logger.debug(“Returning cached instance of singleton bean ‘” + beanName + “‘”);
18 }
19 }
20 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
21 }
22
23 else {24 // Fail if we’re already creating this bean instance: 25 // We’re assumably within a circular reference.
26 if (isPrototypeCurrentlyInCreation(beanName)) {27 throw new BeanCurrentlyInCreationException(beanName); 28 }
29
30 // Check if bean definition exists in this factory.
31 BeanFactory parentBeanFactory = getParentBeanFactory(); 32 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
33 // Not found -> check parent.
34 String nameToLookup = originalBeanName(name); 35 if (args != null) {
36 // Delegation to parent with explicit args.
37 return (T) parentBeanFactory.getBean(nameToLookup, args); 38 }
39 else {40 // No args -> delegate to standard getBean method.
41 return parentBeanFactory.getBean(nameToLookup, requiredType); 42 }
43 }
44
45 if (!typeCheckOnly) {
46 markBeanAsCreated(beanName);
47 }
48
49 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 50 checkMergedBeanDefinition(mbd, beanName, args);
51
52 // Guarantee initialization of beans that the current bean depends on.
53 String[] dependsOn = mbd.getDependsOn(); 54 if (dependsOn != null) {
55 for (String dependsOnBean : dependsOn) {56 getBean(dependsOnBean);
57 registerDependentBean(dependsOnBean, beanName);
58 }
59 }
60
61 // Create bean instance.
62 if (mbd.isSingleton()) {63 sharedInstance = getSingleton(beanName, new ObjectFactory() {64 public Object getObject() throws BeansException {65 try { 66 return createBean(beanName, mbd, args); 67 }
68 catch (BeansException ex) {69 // Explicitly remove instance from singleton cache: It might have been put there 70 // eagerly by the creation process, to allow for circular reference resolution. 71 // Also remove any beans that received a temporary reference to the bean.
72 destroySingleton(beanName);
73 throw ex; 74 }
75 }
76 });
77 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 78 }
79
80 else if (mbd.isPrototype()) {81 // It’s a prototype -> create a new instance.
82 Object prototypeInstance = null;
83 try {84 beforePrototypeCreation(beanName);
85 prototypeInstance = createBean(beanName, mbd, args); 86 }
87 finally {88 afterPrototypeCreation(beanName);
89 }
90 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 91 }
92
93 else {94 String scopeName = mbd.getScope(); 95 final Scope scope = this.scopes.get(scopeName);
96 if (scope == null) {
97 throw new IllegalStateException(“No Scope registered for scope ‘” + scopeName + “‘”);
98 }
99 try {100 Object scopedInstance = scope.get(beanName, new ObjectFactory() {101 public Object getObject() throws BeansException {102 beforePrototypeCreation(beanName); 103 try {104 return createBean(beanName, mbd, args); 105 } 106 finally {107 afterPrototypeCreation(beanName); 108 } 109 } 110 }); 111 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 112 } 113 catch (IllegalStateException ex) {114 throw new BeanCreationException(beanName, 115 “Scope ‘” + scopeName + “‘ is not active for the current thread; ” +
116 “consider defining a scoped proxy for this bean if you intend to refer to it from a singleton”, 117 ex); 118 } 119 } 120 } 121
122 // Check if required type matches the type of the actual bean instance.
123 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {124 try { 125 return getTypeConverter().convertIfNecessary(bean, requiredType); 126 } 127 catch (TypeMismatchException ex) {128 if (logger.isDebugEnabled()) {129 logger.debug(“Failed to convert bean ‘” + name + “‘ to required type [” +
130 ClassUtils.getQualifiedName(requiredType) + “]”, ex); 131 } 132 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 133 } 134 } 135 return (T) bean; 136 }</pre>

首先第 9 行~ 第 21 行的代码,第 9 行的代码就不进去看了,简单说一下:首先检查一下本地的单例缓存是否已经加载过 Bean,没有的话再检查 earlySingleton 缓存是否已经加载过 Bean(又是 early,不好找到词语翻译),没有的话执行后面的逻辑。

接着第 26 行~ 第 50 行,这里执行的都是一些基本的检查和简单的操作,包括 bean 是否是 prototype 的(prototype 的 Bean 当前创建会抛出异常)、是否抽象的、将 beanName 加入 alreadyCreated 这个 Set 中等。

接着第 53 行~ 第 59 行,我们经常在 bean 标签中看到 depends-on 这个属性,就是通过这段保证了 depends-on 依赖的 Bean 会优先于当前 Bean 被加载。

接着第 62 行~ 第 78 行、第 80 行~ 第 91 行、第 93 行~ 第 120 行有三个判断,显然上面的 MultiFunctionBean 是一个单例的 Bean 也是本文探究的重点,因此执行第 62 行~ 第 78 行的逻辑。getSingleton 方法不贴了,有一些前置的判断,很简单的逻辑,重点就是调用了 ObjectFactory 的 getObject() 方法来获取到单例 Bean 对象,方法的实现是调用了 createBean 方法,createBean 方法是 AbstractBeanFactory 的子类 AbstractAutowireCapableBeanFactory 的一个方法,看一下它的方法实现:

<pre> 1 protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 2 throws BeanCreationException {3
4 if (logger.isDebugEnabled()) {5 logger.debug(“Creating instance of bean ‘” + beanName + “‘”);
6 }
7 // Make sure bean class is actually resolved at this point.
8 resolveBeanClass(mbd, beanName);
9
10 // Prepare method overrides.
11 try {12 mbd.prepareMethodOverrides(); 13 } 14 catch (BeanDefinitionValidationException ex) {15 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), 16 beanName, “Validation of method overrides failed”, ex); 17 } 18
19 try {20 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
21 Object bean = resolveBeforeInstantiation(beanName, mbd); 22 if (bean != null) {23 return bean; 24} 25 } 26 catch (Throwable ex) {27 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 28 “BeanPostProcessor before instantiation of bean failed”, ex); 29 } 30
31 Object beanInstance = doCreateBean(beanName, mbd, args); 32 if (logger.isDebugEnabled()) {33 logger.debug(“Finished creating instance of bean ‘” + beanName + “‘”); 34 } 35 return beanInstance; 36 }</pre>

前面的代码都没什么意义,代码执行到第 31 行:

<pre> 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {2 // Instantiate the bean.
3 BeanWrapper instanceWrapper = null;
4 if (mbd.isSingleton()) {5 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
6 }
7 if (instanceWrapper == null) {
8 instanceWrapper = createBeanInstance(beanName, mbd, args); 9 } 10 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); 11 Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); 12
13 // Allow post-processors to modify the merged bean definition.
14 synchronized (mbd.postProcessingLock) {15 if (!mbd.postProcessed) {16 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 17 mbd.postProcessed = true; 18 } 19 } 20
21 // Eagerly cache singletons to be able to resolve circular references 22 // even when triggered by lifecycle interfaces like BeanFactoryAware.
23 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
24 isSingletonCurrentlyInCreation(beanName)); 25 if (earlySingletonExposure) {26 if (logger.isDebugEnabled()) {27 logger.debug(“Eagerly caching bean ‘” + beanName +
28 “‘ to allow for resolving potential circular references”); 29 } 30 addSingletonFactory(beanName, new ObjectFactory() {31 public Object getObject() throws BeansException {32 return getEarlyBeanReference(beanName, mbd, bean); 33 } 34 }); 35 } 36
37 // Initialize the bean instance.
38 Object exposedObject = bean; 39 try {40 populateBean(beanName, mbd, instanceWrapper); 41 if (exposedObject != null) {42 exposedObject = initializeBean(beanName, exposedObject, mbd); 43 } 44 } 45 catch (Throwable ex) {46 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {47 throw (BeanCreationException) ex; 48 } 49 else {50 throw new BeanCreationException(mbd.getResourceDescription(), beanName, “Initialization of bean failed”, ex); 51 } 52 } 53
54 if (earlySingletonExposure) {55 Object earlySingletonReference = getSingleton(beanName, false); 56 if (earlySingletonReference != null) {57 if (exposedObject == bean) {58 exposedObject = earlySingletonReference; 59} 60 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {61 String[] dependentBeans = getDependentBeans(beanName); 62 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); 63 for (String dependentBean : dependentBeans) {64 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {65 actualDependentBeans.add(dependentBean); 66 } 67 } 68 if (!actualDependentBeans.isEmpty()) {69 throw new BeanCurrentlyInCreationException(beanName, 70 “Bean with name ‘” + beanName + “‘ has been injected into other beans [” +
71 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
72 “] in its raw version as part of a circular reference, but has eventually been ” +
73 “wrapped. This means that said other beans do not use the final version of the ” +
74 “bean. This is often the result of over-eager type matching – consider using ” +
75 “‘getBeanNamesOfType’ with the ‘allowEagerInit’ flag turned off, for example.”); 76 } 77 } 78 } 79 } 80
81 // Register bean as disposable.
82 try {83 registerDisposableBeanIfNecessary(beanName, bean, mbd); 84 } 85 catch (BeanDefinitionValidationException ex) {86 throw new BeanCreationException(mbd.getResourceDescription(), beanName, “Invalid destruction signature”, ex); 87 } 88
89 return exposedObject; 90 }</pre>

doCreateBean 方法

代码跟踪到这里,已经到了主流程,接下来分段分析 doCreateBean 方法的代码。

创建 Bean 实例

第 8 行的 createBeanInstance 方法,会创建出 Bean 的实例,并包装为 BeanWrapper,看一下 createBeanInstance 方法,只贴最后一段比较关键的:

<pre> 1 // Need to determine the constructor…
2 Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 3 if (ctors != null ||
4 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
5 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
6 return autowireConstructor(beanName, mbd, ctors, args); 7 }
8
9 // No special handling: simply use no-arg constructor.
10 return instantiateBean(beanName, mbd);</pre>

意思是 bean 标签使用构造函数注入属性的话,执行第 6 行,否则执行第 10 行。MultiFunctionBean 使用默认构造函数,使用 setter 注入属性,因此执行第 10 行代码:

<pre> 1 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {2 try { 3 Object beanInstance;
4 final BeanFactory parent = this;
5 if (System.getSecurityManager() != null) {
6 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
7 public Object run() { 8 return getInstantiationStrategy().instantiate(mbd, beanName, parent); 9 } 10 }, getAccessControlContext()); 11 } 12 else {13 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 14 } 15 BeanWrapper bw = new BeanWrapperImpl(beanInstance); 16 initBeanWrapper(bw); 17 return bw; 18 } 19 catch (Throwable ex) {20 throw new BeanCreationException(mbd.getResourceDescription(), beanName, “Instantiation of bean failed”, ex); 21 } 22 }</pre>

代码执行到 13 行:

<pre> 1 public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {2 // Don’t override the class with CGLIB if no overrides.
3 if (beanDefinition.getMethodOverrides().isEmpty()) {4 Constructor<?> constructorToUse; 5 synchronized (beanDefinition.constructorArgumentLock) {6 constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
7 if (constructorToUse == null) {
8 final Class clazz = beanDefinition.getBeanClass(); 9 if (clazz.isInterface()) {10 throw new BeanInstantiationException(clazz, “Specified class is an interface”); 11 } 12 try {13 if (System.getSecurityManager() != null) {14 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {15 public Constructor run() throws Exception {16 return clazz.getDeclaredConstructor((Class[]) null); 17 } 18 }); 19 } 20 else {21 constructorToUse = clazz.getDeclaredConstructor((Class[]) null); 22 } 23 beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse; 24 } 25 catch (Exception ex) {26 throw new BeanInstantiationException(clazz, “No default constructor found”, ex); 27 } 28 } 29 } 30 return BeanUtils.instantiateClass(constructorToUse); 31 } 32 else {33 // Must generate CGLIB subclass.
34 return instantiateWithMethodInjection(beanDefinition, beanName, owner); 35 } 36 }</pre>

整段代码都在做一件事情,就是选择一个使用的构造函数。当然第 9 行顺带做了一个判断:实例化一个接口将报错。

最后调用到 30 行,看一下代码:

<pre> 1 public static <T> T instantiateClass(Constructor<T> ctor, Object… args) throws BeanInstantiationException {2 Assert.notNull(ctor, “Constructor must not be null”);
3 try {4 ReflectionUtils.makeAccessible(ctor);
5 return ctor.newInstance(args); 6 }
7 catch (InstantiationException ex) {8 throw new BeanInstantiationException(ctor.getDeclaringClass(), 9 “Is it an abstract class?”, ex); 10 } 11 catch (IllegalAccessException ex) {12 throw new BeanInstantiationException(ctor.getDeclaringClass(), 13 “Is the constructor accessible?”, ex); 14 } 15 catch (IllegalArgumentException ex) {16 throw new BeanInstantiationException(ctor.getDeclaringClass(), 17 “Illegal arguments for constructor”, ex); 18 } 19 catch (InvocationTargetException ex) {20 throw new BeanInstantiationException(ctor.getDeclaringClass(), 21 “Constructor threw exception”, ex.getTargetException()); 22 } 23 }</pre>

通过反射生成 Bean 的实例。看到前面有一步 makeAccessible,这意味着即使 Bean 的构造函数是 private、protected 的,依然不影响 Bean 的构造。

最后注意一下,这里被实例化出来的 Bean 并不会直接返回,而是会被包装为 BeanWrapper 继续在后面使用。

doCreateBean 方法

上文【Spring 源码分析】非懒加载的单例 Bean 初始化过程(上篇),分析了单例的 Bean 初始化流程,并跟踪代码进入了主流程,看到了 Bean 是如何被实例化出来的。先贴一下 AbstractAutowireCapableBeanFactory 的 doCreateBean 方法代码:

<pre> 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {2 // Instantiate the bean.
3 BeanWrapper instanceWrapper = null;
4 if (mbd.isSingleton()) {5 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
6 }
7 if (instanceWrapper == null) {
8 instanceWrapper = createBeanInstance(beanName, mbd, args); 9 } 10 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); 11 Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); 12
13 // Allow post-processors to modify the merged bean definition.
14 synchronized (mbd.postProcessingLock) {15 if (!mbd.postProcessed) {16 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 17 mbd.postProcessed = true; 18 } 19 } 20
21 // Eagerly cache singletons to be able to resolve circular references 22 // even when triggered by lifecycle interfaces like BeanFactoryAware.
23 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
24 isSingletonCurrentlyInCreation(beanName)); 25 if (earlySingletonExposure) {26 if (logger.isDebugEnabled()) {27 logger.debug(“Eagerly caching bean ‘” + beanName +
28 “‘ to allow for resolving potential circular references”); 29 } 30 addSingletonFactory(beanName, new ObjectFactory() {31 public Object getObject() throws BeansException {32 return getEarlyBeanReference(beanName, mbd, bean); 33 } 34 }); 35 } 36
37 // Initialize the bean instance.
38 Object exposedObject = bean; 39 try {40 populateBean(beanName, mbd, instanceWrapper); 41 if (exposedObject != null) {42 exposedObject = initializeBean(beanName, exposedObject, mbd); 43 } 44 } 45 catch (Throwable ex) {46 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {47 throw (BeanCreationException) ex; 48 } 49 else {50 throw new BeanCreationException(mbd.getResourceDescription(), beanName, “Initialization of bean failed”, ex); 51 } 52 } 53
54 if (earlySingletonExposure) {55 Object earlySingletonReference = getSingleton(beanName, false); 56 if (earlySingletonReference != null) {57 if (exposedObject == bean) {58 exposedObject = earlySingletonReference; 59} 60 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {61 String[] dependentBeans = getDependentBeans(beanName); 62 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); 63 for (String dependentBean : dependentBeans) {64 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {65 actualDependentBeans.add(dependentBean); 66 } 67 } 68 if (!actualDependentBeans.isEmpty()) {69 throw new BeanCurrentlyInCreationException(beanName, 70 “Bean with name ‘” + beanName + “‘ has been injected into other beans [” +
71 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
72 “] in its raw version as part of a circular reference, but has eventually been ” +
73 “wrapped. This means that said other beans do not use the final version of the ” +
74 “bean. This is often the result of over-eager type matching – consider using ” +
75 “‘getBeanNamesOfType’ with the ‘allowEagerInit’ flag turned off, for example.”); 76 } 77 } 78 } 79 } 80
81 // Register bean as disposable.
82 try {83 registerDisposableBeanIfNecessary(beanName, bean, mbd); 84 } 85 catch (BeanDefinitionValidationException ex) {86 throw new BeanCreationException(mbd.getResourceDescription(), beanName, “Invalid destruction signature”, ex); 87 } 88
89 return exposedObject; 90 }</pre>

下面继续分析初始化一个 Bean 的流程,不太重要的流程就跳过了。

属性注入

属性注入的代码比较好找,可以看一下 40 行,取名为 populateBean,即填充 Bean 的意思,看一下代码实现:

<pre> 1 protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {2 PropertyValues pvs = mbd.getPropertyValues(); 3
4 if (bw == null) {
5 if (!pvs.isEmpty()) {
6 throw new BeanCreationException(7 mbd.getResourceDescription(), beanName, “Cannot apply property values to null instance”);
8 }
9 else {10 // Skip property population phase for null instance.
11 return; 12 } 13 } 14
15 // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the 16 // state of the bean before properties are set. This can be used, for example, 17 // to support styles of field injection.
18 boolean continueWithPropertyPopulation = true; 19
20 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {21 for (BeanPostProcessor bp : getBeanPostProcessors()) {22 if (bp instanceof InstantiationAwareBeanPostProcessor) {23 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 24 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {25 continueWithPropertyPopulation = false; 26 break; 27} 28 } 29 } 30 } 31
32 if (!continueWithPropertyPopulation) {33 return; 34} 35
36 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
37 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {38 MutablePropertyValues newPvs = new MutablePropertyValues(pvs); 39
40 // Add property values based on autowire by name if applicable.
41 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {42 autowireByName(beanName, mbd, bw, newPvs); 43 } 44
45 // Add property values based on autowire by type if applicable.
46 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {47 autowireByType(beanName, mbd, bw, newPvs); 48 } 49
50 pvs = newPvs; 51 } 52
53 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 54 boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); 55
56 if (hasInstAwareBpps || needsDepCheck) {57 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 58 if (hasInstAwareBpps) {59 for (BeanPostProcessor bp : getBeanPostProcessors()) {60 if (bp instanceof InstantiationAwareBeanPostProcessor) {61 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 62 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 63 if (pvs == null) {64 return; 65} 66 } 67 } 68 } 69 if (needsDepCheck) {70 checkDependencies(beanName, mbd, filteredPds, pvs); 71 } 72 } 73
74 applyPropertyValues(beanName, mbd, bw, pvs); 75 }</pre>

这段代码层次有点深,跟一下 74 行的 applyPropertyValues 方法,最后那个 pvs 的实现类为 MutablePropertyValues,里面持有一个 List<PropertyValue>,每一个 PropertyValue 包含了此 Bean 属性的属性名与属性值。74 行的代码实现为:

<pre> 1 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {2 if (pvs == null || pvs.isEmpty()) {3 return;
4 }
5
6 MutablePropertyValues mpvs = null;
7 List<PropertyValue> original; 8
9 if (System.getSecurityManager()!= null) {10 if (bw instanceof BeanWrapperImpl) {11 ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); 12 } 13 } 14
15 if (pvs instanceof MutablePropertyValues) {16 mpvs = (MutablePropertyValues) pvs; 17 if (mpvs.isConverted()) {18 // Shortcut: use the pre-converted values as-is.
19 try {20 bw.setPropertyValues(mpvs); 21 return; 22 } 23 catch (BeansException ex) {24 throw new BeanCreationException( 25 mbd.getResourceDescription(), beanName, “Error setting property values”, ex); 26 } 27 } 28 original = mpvs.getPropertyValueList(); 29} 30 else {31 original = Arrays.asList(pvs.getPropertyValues()); 32 } 33
34 TypeConverter converter = getCustomTypeConverter(); 35 if (converter == null) {36 converter = bw; 37} 38 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); 39
40 // Create a deep copy, resolving any references for values.
41 List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size()); 42 boolean resolveNecessary = false; 43 for (PropertyValue pv : original) {44 if (pv.isConverted()) {45 deepCopy.add(pv); 46 } 47 else {48 String propertyName = pv.getName(); 49 Object originalValue = pv.getValue(); 50 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); 51 Object convertedValue = resolvedValue; 52 boolean convertible = bw.isWritableProperty(propertyName) &&
53 !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); 54 if (convertible) {55 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); 56 } 57 // Possibly store converted value in merged bean definition, 58 // in order to avoid re-conversion for every created bean instance.
59 if (resolvedValue == originalValue) {60 if (convertible) {61 pv.setConvertedValue(convertedValue); 62 } 63 deepCopy.add(pv); 64 } 65 else if (convertible && originalValue instanceof TypedStringValue &&
66 !((TypedStringValue) originalValue).isDynamic() &&
67 !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {68 pv.setConvertedValue(convertedValue); 69 deepCopy.add(pv); 70 } 71 else {72 resolveNecessary = true; 73 deepCopy.add(new PropertyValue(pv, convertedValue)); 74 } 75 } 76 } 77 if (mpvs != null && !resolveNecessary) {78 mpvs.setConverted(); 79 } 80
81 // Set our (possibly massaged) deep copy.
82 try {83 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); 84 } 85 catch (BeansException ex) {86 throw new BeanCreationException( 87 mbd.getResourceDescription(), beanName, “Error setting property values”, ex); 88 } 89 }</pre>

之后在第 41 行~ 第 76 行做了一次深拷贝(只是名字叫做深拷贝而已,其实就是遍历 PropertyValue 然后一个一个赋值到一个新的 List 而不是 Java 语义上的 Clone,这里使用深拷贝是为了解析 Values 值中的所有引用),将 PropertyValue 一个一个赋值到一个新的 List 里面去,起名为 deepCopy。最后执行 83 行进行复制,bw 即 BeanWrapper,持有 Bean 实例的一个 Bean 包装类,看一下代码实现:

<pre> 1 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) 2 throws BeansException {3
4 List<PropertyAccessException> propertyAccessExceptions = null;
5 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
6 ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
7 for (PropertyValue pv : propertyValues) {8 try { 9 // This method may throw any BeansException, which won’t be caught 10 // here, if there is a critical failure such as no matching field. 11 // We can attempt to deal only with less serious exceptions.
12 setPropertyValue(pv); 13 } 14 catch (NotWritablePropertyException ex) {15 if (!ignoreUnknown) {16 throw ex; 17} 18 // Otherwise, just ignore it and continue…
19 } 20 catch (NullValueInNestedPathException ex) {21 if (!ignoreInvalid) {22 throw ex; 23} 24 // Otherwise, just ignore it and continue…
25 } 26 catch (PropertyAccessException ex) {27 if (propertyAccessExceptions == null) {28 propertyAccessExceptions = new LinkedList<PropertyAccessException>(); 29 } 30 propertyAccessExceptions.add(ex); 31 } 32 } 33
34 // If we encountered individual exceptions, throw the composite exception.
35 if (propertyAccessExceptions != null) {36 PropertyAccessException[] paeArray =
37 propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]); 38 throw new PropertyBatchUpdateException(paeArray); 39 } 40 }</pre>

这段代码没什么特别的,遍历前面的 deepCopy,拿每一个 PropertyValue,执行第 12 行的 setPropertyValue:

<pre> 1 public void setPropertyValue(PropertyValue pv) throws BeansException {2 PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens; 3 if (tokens == null) {
4 String propertyName = pv.getName(); 5 BeanWrapperImpl nestedBw;
6 try {7 nestedBw = getBeanWrapperForPropertyPath(propertyName); 8 }
9 catch (NotReadablePropertyException ex) {10 throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, 11 “Nested property in path ‘” + propertyName + “‘ does not exist”, ex); 12 } 13 tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName)); 14 if (nestedBw == this) {15 pv.getOriginalPropertyValue().resolvedTokens = tokens; 16 } 17 nestedBw.setPropertyValue(tokens, pv); 18 } 19 else {20 setPropertyValue(tokens, pv); 21 } 22 }</pre>

找一个合适的 BeanWrapper,这里就是自身,然后执行 17 行的 setPropertyValue 方法进入最后一步,方法非常长,截取核心的一段:

<pre> 1 final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
2 ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
3 pd.getWriteMethod());
4 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
5 if (System.getSecurityManager()!= null) {
6 AccessController.doPrivileged(new PrivilegedAction<Object>() {
7 public Object run() { 8 writeMethod.setAccessible(true);
9 return null; 10 } 11 }); 12 } 13 else {14 writeMethod.setAccessible(true); 15 } 16 } 17 final Object value = valueToApply; 18 if (System.getSecurityManager() != null) {19 try { 20 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {21 public Object run() throws Exception {22 writeMethod.invoke(object, value); 23 return null; 24 } 25 }, acc); 26 } 27 catch (PrivilegedActionException ex) {28 throw ex.getException(); 29 } 30 } 31 else {32 writeMethod.invoke(this.object, value); 33 } </pre>

大致流程就是两步:

(1)拿到写方法并将方法的可见性设置为 true

(2)拿到 Value 值,对 Bean 通过反射调用写方法

这样完成了对于 Bean 属性值的设置。

Aware 注入

接下来是 Aware 注入。在使用 Spring 的时候我们将自己的 Bean 实现 BeanNameAware 接口、BeanFactoryAware 接口等,依赖容器帮我们注入当前 Bean 的名称或者 Bean 工厂,其代码实现先追溯到上面 doCreateBean 方法的 42 行 initializeBean 方法:

<pre> 1 protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {2 if (System.getSecurityManager() != null) {
3 AccessController.doPrivileged(new PrivilegedAction<Object>() {
4 public Object run() { 5 invokeAwareMethods(beanName, bean);
6 return null;
7 }
8 }, getAccessControlContext());
9 } 10 else {11 invokeAwareMethods(beanName, bean); 12 } 13
14 Object wrappedBean = bean; 15 if (mbd == null || !mbd.isSynthetic()) {16 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 17 } 18
19 try {20 invokeInitMethods(beanName, wrappedBean, mbd); 21 } 22 catch (Throwable ex) {23 throw new BeanCreationException( 24 (mbd != null ? mbd.getResourceDescription() : null), 25 beanName, “Invocation of init method failed”, ex); 26 } 27
28 if (mbd == null || !mbd.isSynthetic()) {29 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 30 } 31 return wrappedBean; 32 }</pre>

看一下上面第 5 行的实现:

<pre> 1 private void invokeAwareMethods(final String beanName, final Object bean) {2 if (bean instanceof BeanNameAware) {3 ((BeanNameAware) bean).setBeanName(beanName);
4 }
5 if (bean instanceof BeanClassLoaderAware) {6 ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
7 }
8 if (bean instanceof BeanFactoryAware) {9 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); 10 } 11 }</pre>

看到这里判断,如果 bean 是 BeanNameAware 接口的实现类会调用 setBeanName 方法、如果 bean 是 BeanClassLoaderAware 接口的实现类会调用 setBeanClassLoader 方法、如果是 BeanFactoryAware 接口的实现类会调用 setBeanFactory 方法,注入对应的属性值。

调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法

上面 initializeBean 方法再看 16 行其实现:

<pre> 1 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) 2 throws BeansException {3
4 Object result = existingBean; 5 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {6 result = beanProcessor.postProcessBeforeInitialization(result, beanName); 7 if (result == null) {
8 return result; 9 } 10 } 11 return result; 12 }</pre>

遍历每个 BeanPostProcessor 接口实现,调用 postProcessBeforeInitialization 方法,这个接口的调用时机之后会总结,这里就代码先简单提一下。

调用初始化方法

initializeBean 方法的 20 行,调用 Bean 的初始化方法,看一下实现:

<pre> 1 protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) 2 throws Throwable {3
4 boolean isInitializingBean = (bean instanceof InitializingBean); 5 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod(“afterPropertiesSet”))) {
6 if (logger.isDebugEnabled()) {7 logger.debug(“Invoking afterPropertiesSet() on bean with name ‘” + beanName + “‘”);
8 }
9 if (System.getSecurityManager() != null) {10 try { 11 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {12 public Object run() throws Exception {13 ((InitializingBean) bean).afterPropertiesSet(); 14 return null; 15} 16 }, getAccessControlContext()); 17 } 18 catch (PrivilegedActionException pae) {19 throw pae.getException(); 20 } 21 } 22 else {23 ((InitializingBean) bean).afterPropertiesSet(); 24} 25 } 26
27 if (mbd != null) {28 String initMethodName = mbd.getInitMethodName(); 29 if (initMethodName != null && !(isInitializingBean && “afterPropertiesSet”.equals(initMethodName)) &&
30 !mbd.isExternallyManagedInitMethod(initMethodName)) {31 invokeCustomInitMethod(beanName, bean, mbd); 32 } 33 } 34 }</pre>

看到,代码做了两件事情:

1、先判断 Bean 是否 InitializingBean 的实现类,是的话,将 Bean 强转为 InitializingBean,直接调用 afterPropertiesSet() 方法

2、尝试去拿 init-method,假如有的话,通过反射,调用 initMethod

因此,两种方法各有优劣:使用实现 InitializingBean 接口的方式效率更高一点,因为 init-method 方法是通过反射进行调用的;从另外一个角度讲,使用 init-method 方法之后和 Spring 的耦合度会更低一点。具体使用哪种方式调用初始化方法,看个人喜好。

调用 BeanPostProcessor 的 postProcessAfterInitialization 方法

最后一步,initializeBean 方法的 29 行:

<pre> 1 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 2 throws BeansException {3
4 Object result = existingBean; 5 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {6 result = beanProcessor.postProcessAfterInitialization(result, beanName); 7 if (result == null) {
8 return result; 9 } 10 } 11 return result; 12 }</pre>

同样遍历 BeanPostProcessor,调用 postProcessAfterInitialization 方法。因此对于 BeanPostProcessor 方法总结一下:

1、在初始化每一个 Bean 的时候都会调用每一个配置的 BeanPostProcessor 的方法

2、在 Bean 属性设置、Aware 设置后调用 postProcessBeforeInitialization 方法

3、在初始化方法调用后调用 postProcessAfterInitialization 方法

注册需要执行销毁方法的 Bean

接下来看一下最上面 doCreateBean 方法的第 83 行 registerDisposableBeanIfNecessary(beanName, bean, mbd) 这一句,完成了创建 Bean 的最后一件事情:注册需要执行销毁方法的 Bean。

看一下方法的实现:

<pre> 1 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {2 AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
3 if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {4 if (mbd.isSingleton()) {5 // Register a DisposableBean implementation that performs all destruction 6 // work for the given bean: DestructionAwareBeanPostProcessors, 7 // DisposableBean interface, custom destroy method.
8 registerDisposableBean(beanName,
9 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 10 } 11 else {12 // A bean with a custom scope…
13 Scope scope = this.scopes.get(mbd.getScope()); 14 if (scope == null) {15 throw new IllegalStateException(“No Scope registered for scope ‘” + mbd.getScope() + “‘”); 16 } 17 scope.registerDestructionCallback(beanName, 18 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 19 } 20 } 21 }</pre>

其中第 3 行第一个判断为必须不是 prototype(原型)的,第二个判断 requiresDestruction 方法的实现为:

<pre>1 protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {2 return (bean != null &&
3 (bean instanceof DisposableBean || mbd.getDestroyMethodName() != null ||
4 hasDestructionAwareBeanPostProcessors())); 5 }</pre>

要注册销毁方法,Bean 需要至少满足以下三个条件之一:

(1)Bean 是 DisposableBean 的实现类,此时执行 DisposableBean 的接口方法 destroy()

(2)Bean 标签中有配置 destroy-method 属性,此时执行 destroy-method 配置指定的方法

(3)当前 Bean 对应的 BeanFactory 中持有 DestructionAwareBeanPostProcessor 接口的实现类,此时执行 DestructionAwareBeanPostProcessor 的接口方法 postProcessBeforeDestruction

在满足上面三个条件之一的情况下,容器便会注册销毁该 Bean,注册 Bean 的方法很简单,见 registerDisposableBean 方法实现:

<pre>1 public void registerDisposableBean(String beanName, DisposableBean bean) {2 synchronized (this.disposableBeans) {3 this.disposableBeans.put(beanName, bean); 4 } 5 }</pre>

容器销毁的时候,会遍历 disposableBeans,逐一执行销毁方法。

流程总结

本文和上篇文章分析了 Spring Bean 初始化的步骤,最后用一幅图总结一下 Spring Bean 初始化的流程:

图只是起梳理流程作用,抛砖引玉,具体代码实现还需要网友朋友们照着代码自己去一步一步分析。

微信公众号【黄小斜】作者是蚂蚁金服 JAVA 工程师,专注于 JAVA
后端技术栈:SpringBoot、SSM 全家桶、MySQL、分布式、中间件、微服务,同时也懂点投资理财,坚持学习和写作,相信终身学习的力量!关注公众号后回复”架构师“即可领取
Java 基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的 Java 学习指南、Java 程序员面试指南等干货资源

正文完
 0