spring - IOC高级特性

介绍

Spring IOC 容器对 Bean 定
义资源的定位、读入和解析过程,同时也清楚了当用户通过 getBean 方法向 IOC 容器获取被管理的 Bean
时,IOC 容器对 Bean 进行的初始化和依赖注入过程,这些是 Spring IOC 容器的基本功能特性。
Spring IOC 容器还有一些高级特性,如使用 lazy-init 属性对 Bean 预初始化、FactoryBean 产生或者
修饰 Bean 对象的生成、IOC 容器初始化 Bean 过程中使用 BeanPostProcessor 后置处理器对 Bean 声明周
期事件管理和 IOC 容器的 autowiring 自动装配功能等。

Spring IOC 容器的 lazy-init 属性实现预实例化:

IOC 容器的初始化过程就是对 Bean 定义
资源的定位、载入和注册,此时容器对 Bean 的依赖注入并没有发生,依赖注入主要是在应用程序第一
次向容器索取 Bean 时,通过 getBean 方法的调用完成。

当 Bean 定义资源的元素中配置了 lazy-init 属性时,容器将会在初始化的时候对所配置的 Bean
进行预实例化,Bean 的依赖注入在容器初始化的时候就已经完成。这样,当应用程序第一次向容器索取
被管理的 Bean 时,就不用再初始化和对 Bean 进行依赖注入了,直接从容器中获取已经完成依赖注入的
现成 Bean,可以提高应用第一次向容器获取 Bean 的性能。

下面我们通过代码分析容器预实例化的实现过程:

refresh()

先从 IOC 容器的初始会过程开始,通过前面文章分析,我们知道 IOC 容器读入已经定位的 Bean 定义资
源是从 refresh 方法开始的,我们首先从 AbstractApplicationContext 类的 refresh 方法入手分析,
源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// 容器初始化的过程,读入 Bean 定义资源,并解析注册
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识.
prepareRefresh();

//告诉子类启动 refreshBeanFactory()方法,Bean 定义资源文件的载入从子类的 refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

//为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);

try {
//以下三个方法其实都是加载一些所谓的监听器(ApplicationAware/SessionAware等等)

// Allows post-processing of the bean factory in context subclasses.
//为容器的某些子类指定特殊的 BeanPost 事件处理器
//比如监听spring是否启动,ApplicationAware中的setApplicationContext方法就可以进行一些容器初始化事件操作
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
//调用所有注册的 BeanFactoryPostProcessor 的 Bean
invokeBeanFactoryPostProcessors(beanFactory);

//为 BeanFactory 注册 BeanPost 事件处理器.
//BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

//初始化信息源,和国际化相关.
// Initialize message source for this context.
initMessageSource();

//初始化容器事件传播器.
// Initialize event multicaster for this context.
initApplicationEventMulticaster();

//调用子类的某些特殊 Bean 初始化方法
// Initialize other special beans in specific context subclasses.
onRefresh();

//为事件传播器注册事件监听器.
// Check for listener beans and register them.
registerListeners();

//初始化所有剩余的单例 Bean.
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
//销毁以创建的单态 Bean
// Destroy already created singletons to avoid dangling resources.
destroyBeans();

//取消 refresh 操作,重置容器的同步标识.
// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}
}
}

在 refresh 方法中 ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();
启动了 Bean 定义资源的载入、注册过程,而 finishBeanFactoryInitialization 方法是对注册后的 Bean
定义中的预实例化(lazy-init=false,Spring 默认就是预实例化,即为 true)的 Bean 进行处理的地方。

finishBeanFactoryInitialization 处理预实例化 Bean

当Bean定义资源被载入IOC容器之后,容器将Bean定义资源解析为容器内部的数据结构BeanDefinition
注册到容器中,AbstractApplicationContext 类中的 finishBeanFactoryInitialization 方法对配置了
预实例化属性的 Bean 进行预初始化过程,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//对配置了 lazy-init 属性的 Bean 进行预实例化处理
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
//这是 Spring3 以后新加的代码,为容器指定一个转换服务(ConversionService)
//在对某些 Bean 属性进行转换时使用
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// Stop using the temporary ClassLoader for type matching.
//为了类型匹配,停止使用临时的类加载器
beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.
//缓存容器中所有注册的 BeanDefinition 元数据,以防被修改
beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.
//对配置了 lazy-init 属性的单态模式 Bean 进行预实例化处理
beanFactory.preInstantiateSingletons();
}

ConfigurableListableBeanFactory 是一个接口,其 preInstantiateSingletons 方法由其子类
DefaultListableBeanFactory 提供。

DefaultListableBeanFactory 对配置 lazy-init 属性单态 Bean 的预实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//对配置 lazy-init 属性单态 Bean 的预实例化
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
List<String> beanNames;
//在对配置 lazy-init 属性单态 Bean 的预实例化过程中,必须多线程同步,以确保数据一致性
synchronized (this.beanDefinitionMap) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
for (String beanName : beanNames) {
//获取指定名称的 Bean 定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Bean 不是抽象的,是单态模式的,且 lazy-init 属性配置为 false
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名称的 bean 是创建容器的 Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,当 Bean 名称前面加”&”符号
//时,获取的是产生容器对象本身,而不是容器产生的 Bean.
//调用 getBean 方法,触发容器对 Bean 实例化和依赖注入过程
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
//标识是否需要预实例化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
//一个匿名内部类
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//调用 getBean 方法,触发容器对 Bean 实例化和依赖注入过程
getBean(beanName);
}
}
else {
//调用 getBean 方法,触发容器对 Bean 实例化和依赖注入过程
getBean(beanName);
}
}
}
}

通过对 lazy-init 处理源码的分析,我们可以看出,如果设置了 lazy-init 属性,则容器在完成 Bean
定义的注册之后,会通过 getBean 方法,触发对指定 Bean 的初始化和依赖注入过程,这样当应用第一
次向容器索取所需的 Bean 时,容器不再需要对 Bean 进行初始化和依赖注入,直接从已经完成实例化和
依赖注入的 Bean 中取一个现成的 Bean,这样就提高了第一次获取 Bean 的性能。

FactoryBean 的实现

在 Spring 中,有两个很容易混淆的类:BeanFactory 和 FactoryBean。
BeanFactory:Bean 工厂,是一个工厂(Factory),我们 Spring IOC 容器的最顶层接口就是这个
BeanFactory,它的作用是管理 Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依
赖。

FactoryBean:工厂 Bean,是一个 Bean,作用是产生其他 bean 实例。通常情况下,这种 bean 没有什么
特别的要求,仅需要提供一个工厂方法,该方法用来返回其他 bean 实例。通常情况下,bean 无须自己
实现工厂模式,Spring 容器担任工厂角色;但少数情况下,容器中的 bean 本身就是工厂,其作用是产
生其它 bean 实例。

当用户使用容器本身时,可以使用转义字符”&”来得到 FactoryBean 本身,以区别通过 FactoryBean
产生的实例对象和 FactoryBean 对象本身。在 BeanFactory 中通过如下代码定义了该转义字符:
StringFACTORY_BEAN_PREFIX = “&”;

如果 myJndiObject 是一个 FactoryBean,则使用&myJndiObject 得到的是 myJndiObject 对象,而不是
myJndiObject 产生出来的对象。

FactoryBean 的源码如下

1
2
3
4
5
6
7
8
9
10
//工厂 Bean,用于产生其他对象
public interface FactoryBean<T> {
//获取容器管理的对象实例
T getObject() throws Exception;
//获取 Bean 工厂创建的对象的类型
Class<?> getObjectType();
//Bean 工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例
//对象,每次请求都返回同一个实例对象
boolean isSingleton();
}

AbstractBeanFactory 的 getBean 方法调用 FactoryBean

在前面我们分析 Spring IOC 容器实例化 Bean 并进行依赖注入过程的源码时,提到在 getBean 方法触
发容器实例化 Bean 的时候会调用 AbstractBeanFactory 的 doGetBean 方法来进行实例化的过程,源码
如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//真正实现向 IOC 容器获取 Bean 的功能,也是触发依赖注入功能的地方
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//根据指定的名称获取被管理 Bean 的名称,剥离指定名称中对容器的相关依赖
//如果指定的是别名,将别名转换为规范的 Bean 名称
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
//先从缓存中取是否已经有被创建过的单态类型的 Bean
//对于单例模式的 Bean 整个 IOC 容器中只创建一次,不需要重复创建
Object sharedInstance = getSingleton(beanName);
//IOC 容器创建单例模式 Bean 实例对象
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
//如果指定名称的 Bean 在容器中已有单例模式的 Bean 被创建
//直接返回已经创建的 Bean
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//获取给定 Bean 的实例对象,主要是完成 FactoryBean 的相关处理
//注意:BeanFactory 是管理容器中 Bean 的工厂,而 FactoryBean 是创建创建对象的工厂 Bean,两者之间有区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//缓存没有正在创建的单例模式 Bean
//缓存中已经有已经创建的原型模式 Bean
//但是由于循环引用的问题导致实例化对象失败
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// Check if bean definition exists in this factory.
//对 IOC 容器中是否存在指定名称的 BeanDefinition 进行检查,首先检查是否
//能在当前的 BeanFactory 中获取的所需要的 Bean,如果不能则委托当前容器
//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
// 为什么要委托父容器去找呢?
// ioc容器是可以被关联的:FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent)
BeanFactory parentBeanFactory = getParentBeanFactory();
//当前容器的父级容器存在,且当前容器中不存在指定名称的 Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//解析指定 Bean 名称的原始名称
// 因为有可能是通过别名去获取bean
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
//委派父级容器根据指定名称和显式的参数查找
// 为什么不传类型再去校验一次?
// 因为这一步是强转成T , 如果类型不一样, 在后续的调用中会报错ClassCastException
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
//委派父级容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//创建的 Bean 是否需要进行类型验证,一般不需要
if (!typeCheckOnly) {
//向容器标记指定的 Bean 已经被创建
markBeanAsCreated(beanName);
}

try {
//根据指定 Bean 名称获取其父级的 Bean 定义
//主要解决 Bean 继承时子类合并父类公共属性问题
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
//获取当前 Bean 所有依赖 Bean 的名称
String[] dependsOn = mbd.getDependsOn();
//如果当前 Bean 有依赖 Bean
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
//递归调用 getBean 方法,获取当前 Bean 的依赖 Bean
getBean(dependsOnBean);
//把被依赖 Bean 注册给当前依赖的 Bean
registerDependentBean(dependsOnBean, beanName);
}
}

// Create bean instance.
//创建单例模式 Bean 的实例对象
if (mbd.isSingleton()) {
//这里使用了一个匿名内部类,创建 Bean 实例对象,并且注册给所依赖的对象
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
//创建一个指定 Bean 实例对象,如果有父级继承,则合并子类和父类的定义
// AbstractAutowireCapableBeanFactory 中实现了该方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
//显式地从容器单例模式 Bean 缓存中清除实例对象
// 其实就是从各种map中吧这个对象给remove掉
destroySingleton(beanName);
throw ex;
}
}
});
//获取给定 Bean 的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//IOC 容器创建原型模式 Bean 实例对象
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
//原型模式(Prototype)是每次都会创建一个新的对象
Object prototypeInstance = null;
try {
//回调 beforePrototypeCreation 方法,默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
//创建指定 Bean 对象实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//回调 afterPrototypeCreation 方法,默认的功能告诉 IoC 容器指定 Bean 的原型对象不再创建了
//就是该bean已经从ing状态变成了ed状态
afterPrototypeCreation(beanName);
}
//获取给定 Bean 的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//要创建的 Bean 既不是单例模式,也不是原型模式,则根据 Bean 定义资源中
//配置的生命周期范围,选择实例化 Bean 的合适方法,这种在 Web 应用程序中
//比较常用,如:request、session、application 等生命周期
else {
String scopeName = mbd.getScope();
//其实scopt也是用map去管理的, 这样的很多地方就能理解通了
final Scope scope = this.scopes.get(scopeName);
//Bean 定义资源中没有配置生命周期范围,则 Bean 定义不合法
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
//这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
// AbstractAutowireCapableBeanFactory 中实现了该方法
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
//获取给定 Bean 的实例对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// Check if required type matches the type of the actual bean instance.
//对创建的 Bean 实例对象进行类型检查
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//获取给定 Bean 的实例对象,主要是完成 FactoryBean 的相关处理
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

//容器已经得到了 Bean 实例对象,这个实例对象可能是一个普通的 Bean,
//也可能是一个工厂 Bean,如果是一个工厂 Bean,则使用它创建一个 Bean 实例对象,
//如果调用本身就想获得一个容器的引用,则指定返回这个工厂 Bean 实例对象
//如果指定的名称是容器的解引用(dereference,即是对象本身而非内存地址),
//且 Bean 实例也不是创建 Bean 实例对象的工厂 Bean
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// name 是否是工厂bean标记
// beanInstance 是否继承factoryBean
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}

// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// 1、true || false 普通类 纯的普通类
// 2、false || true 工厂类 纯的工厂
// 3、false || false 普通类 没有定义为工厂的普通工厂类
//如果 Bean 实例不是工厂 Bean,或者指定名称是容器的解引用,
//调用者向获取对容器的引用,则直接返回当前的 Bean 实例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//处理指定名称不是容器的解引用,或者根据名称获取的 Bean 实例对象是一个工厂 Bean
//使用工厂 Bean 创建一个 Bean 的实例对象
Object object = null;
if (mbd == null) {
// 真正的ioc容器
//从 Bean 工厂缓存中获取给定名称的 Bean 实例对象
object = getCachedObjectForFactoryBean(beanName);
}
//让 Bean 工厂生产给定名称的 Bean 对象实例
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//如果从 Bean 工厂生产的 Bean 是单态模式的,则缓存
if (mbd == null && containsBeanDefinition(beanName)) {
//从容器中获取指定名称的 Bean 定义,如果继承基类,则合并基类相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否是合成的,意思就是是否当做工具类来使用
// 这里的synthetic实际上是为了给用户自定义一些BeanDefinition注册到容器中以当作工具类来使用。
// 什么是synthetic
// 就是内部类,java在编译的时候内部类也会编译成单独的一个文件,那实际上,原始类及时两个类的合成类
// 工具类就没有必要做一些封装、代理等工作,实际上是拿来就用,没有其他处理
// 对于synthetic类型的BeanDefinition,getObjectFromFactoryBean中是不会对FactoryBean生成的bean用post-processor进行后置处理的。
// 后置处理的实现是在AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean中,
// 它会调用容器中的BeanPostProcessor.postProcessAfterInitialization,这里提供了一个扩展点对FactoryBean生成的bean进行封装,代理等
//如果从容器得到 Bean 定义信息,并且 Bean 定义信息不是虚构的,
//则让工厂 Bean 生产 Bean 实例对象
boolean synthetic = (mbd != null && mbd.isSynthetic());
// bean实例化的缓存
//调用 FactoryBeanRegistrySupport 类的 getObjectFromFactoryBean 方法,
//实现工厂 Bean 生产 Bean 对象实例的过程
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

在上面获取给定 Bean 的实例对象的 getObjectForBeanInstance 方法中,会调用
FactoryBeanRegistrySupport 类的 getObjectFromFactoryBean 方法,该方法实现了 Bean 工厂生产 Bean
实例对象。

Dereference(解引用):一个在 C/C中应用比较多的术语,在 C中,*是解引用符号,而&
引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址。

AbstractBeanFactory 生产 Bean 实例对象

AbstractBeanFactory 类中生产 Bean 实例对象的主要源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Bean 工厂生产 Bean 实例对象
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//Bean 工厂是单态模式,并且 Bean 工厂缓存中存在指定名称的 Bean 实例对象
if (factory.isSingleton() && containsSingleton(beanName)) {
//多线程同步,以防止数据不一致
synchronized (getSingletonMutex()) {
//直接从 Bean 工厂缓存中获取指定名称的 Bean 实例对象
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//调用 Bean 工厂的 getObject 方法生产指定 Bean 的实例对象
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
//将生产的实例对象添加到 Bean 工厂缓存中
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}
}
//调用 Bean 工厂的 getObject 方法生产指定 Bean 的实例对象
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//调用 Bean 工厂的 getObject 方法生产指定 Bean 的实例对象
private Object doGetObjectFromFactoryBean(
final FactoryBean<?> factory, final String beanName, final boolean shouldPostProcess)
throws BeanCreationException {

Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
//实现 PrivilegedExceptionAction 接口的匿名内置类
//根据 JVM 检查权限,然后决定 BeanFactory 创建实例对象
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
//调用 BeanFactory 接口实现类的创建对象方法
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//调用 BeanFactory 接口实现类的创建对象方法
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}


// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
//创建出来的实例对象为 null,或者因为单态对象正在创建而返回 null
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
//为创建出来的 Bean 实例对象添加 BeanPostProcessor 后置处理器
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
}
}

return object;
}

从上面的源码分析中,我们可以看出,BeanFactory 接口调用其实现类的 getObject 方法来实现创建 Bean
实例对象的功能

工厂 Bean 的实现类 getObject 方法创建 Bean 实例对象

FactoryBean的实现类有非常多,比如:Proxy、RMI、JNDI、ServletContextFactoryBean等等,FactoryBean
接口为 Spring 容器提供了一个很好的封装机制,具体的 getObject 有不同的实现类根据不同的实现策
略来具体提供,我们分析一个最简单的 AnnotationTestFactoryBean 的实现源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class AnnotationTestBeanFactory implements FactoryBean<FactoryCreatedAnnotationTestBean> {

private final FactoryCreatedAnnotationTestBean instance = new FactoryCreatedAnnotationTestBean();

public AnnotationTestBeanFactory() {
this.instance.setName("FACTORY");
}

@Override
//AnnotationTestBeanFactory 产生 Bean 实例对象的实现
public FactoryCreatedAnnotationTestBean getObject() throws Exception {
return this.instance;
}

@Override
public Class<? extends IJmxTestBean> getObjectType() {
return FactoryCreatedAnnotationTestBean.class;
}

@Override
public boolean isSingleton() {
return true;
}

}

其他的 Proxy,RMI,JNDI 等等,都是根据相应的策略提供 getObject 的实现。这里不做一一分析,这
已经不是 Spring 的核心功能,有需要的时候再去深入研究。

BeanPostProcessor 后置处理器的实现

BeanPostProcessor 后置处理器是 Spring IOC 容器经常使用到的一个特性,这个 Bean 后置处理器是一
个监听器,可以监听容器触发的 Bean 声明周期事件。后置处理器向容器注册以后,容器中管理的 Bean
就具备了接收 IOC 容器事件回调的能力。

BeanPostProcessor 的使用非常简单,只需要提供一个实现接口 BeanPostProcessor 的实现类,然后在
Bean 的配置文件中设置即可。

BeanPostProcessor 的源码如下

1
2
3
4
5
6
7
8
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
public interface BeanPostProcessor {
//为在 Bean 的初始化前提供回调入口
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//为在 Bean 的初始化之后提供回调入口
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

这两个回调的入口都是和容器管理的 Bean 的生命周期事件紧密相关,可以为用户提供在 Spring IOC
容器初始化 Bean 过程中自定义的处理操作。

AbstractAutowireCapableBeanFactory 类对容器生成的 Bean 添加后置处理器

BeanPostProcessor后置处理器的调用发生在Spring IOC容器完成对Bean实例对象的创建和属性的依
赖注入完成之后,在对 Spring 依赖注入的源码分析过程中我们知道,当应用程序第一次调用 getBean
方法(lazy-init 预实例化除外)向 Spring IOC 容器索取指定 Bean 时触发 Spring IOC 容器创建 Bean
实例对象并进行依赖注入的过程,其中真正实现创建 Bean 对象并进行依赖注入的方法是
AbstractAutowireCapableBeanFactory 类的 doCreateBean 方法,主要源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//真正创建 Bean 的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//创建 Bean 实例对象
……
try {
//对 Bean 属性进行依赖注入
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//在对 Bean 实例对象生成和依赖注入完成以后,开始对 Bean 实例对象
//进行初始化 ,为 Bean 实例对象应用 BeanPostProcessor 后置处理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)
ex).getBeanName())) {
throw (BeanCreationException) ex;
}
……
//为应用返回所需要的实例对象
return exposedObject;
}

从上面的代码中我们知道,为 Bean 实例对象添加 BeanPostProcessor 后置处理器的入口的是
initializeBean 方法。

initializeBean 方法为容器产生的 Bean 实例对象添加 BeanPostProcessor 后置处理器

同样在 AbstractAutowireCapableBeanFactory 类中,initializeBean 方法实现为容器创建的 Bean 实例
对象添加 BeanPostProcessor 后置处理器,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//初始容器创建的 Bean 实例对象,为其添加 BeanPostProcessor 后置处理器
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//JDK 的安全机制验证权限
if (System.getSecurityManager() != null) {
//实现 PrivilegedAction 接口的匿名内部类
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
//为 Bean 实例对象包装相关属性,如名称,类加载器,所属容器等信息
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
//对 BeanPostProcessor 后置处理器的 postProcessBeforeInitialization
//回调方法的调用,为 Bean 实例初始化前做一些处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//调用 Bean 实例对象初始化的方法,这个初始化方法是在 Spring Bean 定义配置
//文件中通过 init-method 属性指定的
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//对 BeanPostProcessor 后置处理器的 postProcessAfterInitialization
//回调方法的调用,为 Bean 实例初始化之后做一些处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//调用 BeanPostProcessor 后置处理器实例对象初始化之前的处理方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
//遍历容器为所创建的 Bean 添加的所有 BeanPostProcessor 后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用 Bean 实例所有的后置处理中的初始化前处理方法,为 Bean 实例对象在
//初始化之前做一些自定义的处理操作
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}

//调用 BeanPostProcessor 后置处理器实例对象初始化之后的处理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
//遍历容器为所创建的 Bean 添加的所有 BeanPostProcessor 后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用 Bean 实例所有的后置处理中的初始化后处理方法,为 Bean 实例对象在
//初始化之后做一些自定义的处理操作
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}

BeanPostProcessor 是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实
现,在 Spring 中,BeanPostProcessor 的实现子类非常的多,分别完成不同的操作,如:AOP 面向切面
编程的注册通知适配器、Bean 对象的数据校验、Bean 继承属性/方法的合并等等,我们以最简单的 AOP
切面织入来简单了解其主要的功能。

AdvisorAdapterRegistrationManager 在 Bean 对象初始化后注册通知适配器

AdvisorAdapterRegistrationManager 是 BeanPostProcessor 的一个实现类,其主要的作用为容器中管
理的 Bean 注册一个面向切面编程的通知适配器,以便在 Spring 容器为所管理的 Bean 进行面向切面编
程时提供方便,其源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//为容器中管理的 Bean 注册一个面向切面编程的通知适配器
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {
//容器中负责管理切面通知适配器注册的对象
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();


/**
* Specify the AdvisorAdapterRegistry to register AdvisorAdapter beans with.
* Default is the global AdvisorAdapterRegistry.
* @see GlobalAdvisorAdapterRegistry
*/
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}

//BeanPostProcessor 在 Bean 对象初始化前的操作
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//没有做任何操作,直接返回容器创建的 Bean 对象
return bean;
}
//BeanPostProcessor 在 Bean 对象初始化后的操作
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AdvisorAdapter){
//如果容器创建的 Bean 实例对象是一个切面通知适配器,则向容器的注册
this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
}
return bean;
}

}

其他的 BeanPostProcessor 接口实现类的也类似,都是对 Bean 对象使用到的一些特性进行处理,或者
向 IOC 容器中注册,为创建的 Bean 实例对象做一些自定义的功能增加,这些操作是容器初始化 Bean 时
自动触发的,不需要认为的干预。

Spring IOC 容器 autowiring 实现原理

Spring IOC 容器提供了两种管理 Bean 依赖关系的方式:

  • 显式管理:通过 BeanDefinition 的属性值和构造方法实现 Bean 依赖关系管理。
  • autowiring:Spring IOC 容器的依赖自动装配功能,不需要对 Bean 属性的依赖关系做显式的声明,只需要在配置好 autowiring 属性,IOC 容器会自动使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中管理的 Bean,从而自动地完成依赖注入。

通过对 autowiring 自动装配特性的理解,我们知道容器对 Bean 的自动装配发生在容器对 Bean 依赖注
入的过程中。在前面对 Spring IOC 容器的依赖注入过程源码分析中,我们已经知道了容器对 Bean 实
例对象的属性注入的处理发生在 AbstractAutoWireCapableBeanFactory 类中的 populateBean 方法中,
我们通过程序流程分析 autowiring 的实现原理

AbstractAutoWireCapableBeanFactory 对 Bean 实例进行属性依赖注入

应用第一次通过 getBean 方法(配置了 lazy-init 预实例化属性的除外)向 IoC 容器索取 Bean 时,容器
创建 Bean 实例对象,并且对 Bean 实例对象进行属性依赖注入,AbstractAutoWireCapableBeanFactory
的 populateBean 方法就是实现 Bean 属性依赖注入的功能,其主要源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
//获取 Bean 定义的属性值,并对属性值进行处理
PropertyValues pvs = mbd.getPropertyValues();
……
//对依赖注入处理,首先处理 autowiring 自动装配的依赖注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {

MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//根据 Bean 名称进行 autowiring 自动装配处理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根据 Bean 类型进行 autowiring 自动装配处理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
}
//对非 autowiring 的属性进行依赖注入处理
……
}

Spring IOC 容器根据 Bean 名称或者类型进行 autowiring 自动依赖注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//根据名称对属性进行自动依赖注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//对 Bean 对象中非简单属性(不是简单继承的对象,如 8 中原始类型,字符串,URL 等都是简单属性)进行处理
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
//如果 Spring IOC 容器中包含指定名称的 Bean
if (containsBean(propertyName)) {
//使用当前Bean的属性名,在IoC容器中获取对应的bean,让将获取的bean设置为当前的Bean的属性值
//调用 getBean 方法向 IoC 容器索取指定名称的 Bean 实例,迭代触发属性的初始化和依赖注入
Object bean = getBean(propertyName);
//为指定名称的属性赋予属性值
pvs.add(propertyName, bean);
//指定名称属性注册依赖 Bean 名称,进行属性依赖注入
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}


//根据类型对属性进行自动依赖注入
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取用户定义的类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//存放解析的要注入的属性
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
//对 Bean 对象中非简单属性(不是简单继承的对象,如 8 中原始类型,字符
//URL 等都是简单属性)进行处理
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//获取指定属性名称的属性描述器
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
//不对 Object 类型的属性进行 autowiring 自动依赖注入
if (!Object.class.equals(pd.getPropertyType())) {
//获取属性的 setter 方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
//检查指定类型是否可以被转换为目标对象的类型
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
//创建一个要被注入的依赖描述
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//根据容器的 Bean 定义解析依赖关系,返回所有要被注入的 Bean 对象
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
//为属性赋值所引用的对象
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//指定名称属性注册依赖 Bean 名称,进行属性依赖注入
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
//释放已自动注入的属性
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}

通过上面的源码分析,我们可以看出来通过属性名进行自动依赖注入的相对比通过属性类型进行自动依
赖注入要稍微简单一些,但是真正实现属性注入的是 DefaultSingletonBeanRegistry 类的
registerDependentBean 方法。

DefaultSingletonBeanRegistry 的 registerDependentBean 方法对属性注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//为指定的 Bean 注入依赖的 Bean
public void registerDependentBean(String beanName, String dependentBeanName) {
//处理 Bean 名称,将别名转换为规范的 Bean 名称
String canonicalName = canonicalName(beanName);
// 翻译一下就是:set里的bean都要依赖 key
//先从容器中:bean 名称-->全部依赖 Bean 名称集合找查找给定名称 Bean 的依赖 Bean
//多线程同步,保证容器内数据的一致性
synchronized (this.dependentBeanMap) {
//获取给定名称 Bean 的所有依赖 Bean 名称
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
//为 Bean 设置依赖 Bean 信息
dependentBeans = new LinkedHashSet<String>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
//向容器中:bean 名称-->全部依赖 Bean 名称集合添加 Bean 的依赖信息
//即,将 Bean 所依赖的 Bean 添加到容器的集合中
dependentBeans.add(dependentBeanName);
}
// 翻译一下就是:key需要依赖set中的bean
//从容器中:bean 名称-->指定名称 Bean 的依赖 Bean 集合找查找给定名称 Bean 的依赖 Bean
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<String>(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
//向容器中:bean 名称-->指定 Bean 的依赖 Bean 名称集合添加 Bean 的依赖信息
//即,将 Bean 所依赖的 Bean 添加到容器的集合中
dependenciesForBean.add(canonicalName);
}
}

通过对 autowiring 的源码分析,我们可以看出,autowiring 的实现过程:

  • 对 Bean 的属性代调用 getBean 方法,完成依赖 Bean 的初始化和依赖注入。
  • 将依赖 Bean 的属性引用设置到被依赖的 Bean 属性上。
  • 将依赖 Bean 的名称和被依赖 Bean 的名称存储在 IOC 容器的集合中。

Spring IOC 容器的 autowiring 属性自动依赖注入是一个很方便的特性,可以简化开发时的配置,但是凡是都有两面性,
自动属性依赖注入也有不足,首先,Bean 的依赖关系在配置文件中无法很清楚地看出来,对于维护造成一定困难。其
次,由于自动依赖注入是 Spring 容器自动执行的,容器是不会智能判断的,如果配置不当,将会带来无法预料的后果,
所以自动依赖注入特性在使用时还是综合考虑。

Jeff-Eric wechat