- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅谈Spring IoC容器的依赖注入原理由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文介绍了浅谈spring ioc容器的依赖注入原理,分享给大家,具体如下:
ioc容器初始化的过程,主要完成的工作是在ioc容器中建立 beandefinition 数据映射,并没有看到ioc容器对bean依赖关系进行注入.
假设当前ioc容器已经载入用户定义的bean信息,依赖注入主要发生在两个阶段 。
正常情况下,由用户第一次向ioc容器索要bean时触发 。
但我们可以在 beandefinition 信息中通过控制 lazy-init 属性来让容器完成对bean的预实例化,即在初始化的过程中就完成某些bean的依赖注入的过程 。
1.getbean触发的依赖注入 。
在基本的ioc容器接口 beanfactory 中,有一个 getbean 的接口定义,这个接口的实现就是触发依赖注入发生的地方.为了进一步了解这个依赖注入的过程,我们从 defaultlistablebeanfactory 的基类 abstractbeanfactory 入手去看看getbean的实现 。
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
|
// 这里是对 beanfactory 接口的实现,比如getbean接口方法
//这些getbean接口方法最终是通过调用dogetbean来实现的
@override
public
object getbean(string name)
throws
beansexception {
return
dogetbean(name,
null
,
null
,
false
);
}
@override
public
<t> t getbean(string name,
class
<t> requiredtype)
throws
beansexception {
return
dogetbean(name, requiredtype,
null
,
false
);
}
@override
public
object getbean(string name, object... args)
throws
beansexception {
return
dogetbean(name,
null
, args,
false
);
}
public
<t> t getbean(string name,
class
<t> requiredtype, object... args)
throws
beansexception {
return
dogetbean(name, requiredtype, args,
false
);
}
//这里是实际取得bean的地方,也就是触发依赖注入发生的地方
@suppresswarnings
(
"unchecked"
)
protected
<t> t dogetbean(
final
string name,
final
class
<t> requiredtype,
final
object[] args,
boolean
typecheckonly)
throws
beansexception {
final
string beanname = transformedbeanname(name);
object bean;
// eagerly check singleton cache for manually registered singletons.
//急切地检查单例人士缓存手动注册的单例
//先从缓存中取得bean,处理那些已经被创建过的单例bean,这种bean不要重复创建
object sharedinstance = getsingleton(beanname);
if
(sharedinstance !=
null
&& args ==
null
) {
if
(logger.isdebugenabled()) {
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 +
"'"
);
}
}
//这里的getobjectforbeaninstance完成的是factorybean的相关处理,以取得factorybean的相关处理,以取得factorybean的生产结果,beanfactory和factorybean的区别已在前面讲过,这个过程在后面还会详细地分析
bean = getobjectforbeaninstance(sharedinstance, name, beanname,
null
);
}
else
{
// fail if we're already creating this bean instance:
// we're assumably within a circular reference.
if
(isprototypecurrentlyincreation(beanname)) {
throw
new
beancurrentlyincreationexception(beanname);
}
// // 检查ioc容器中的beandefinition是否存在,若在当前工厂不存在则去顺着双亲beanfactory链一直向上找
beanfactory parentbeanfactory = getparentbeanfactory();
if
(parentbeanfactory !=
null
&& !containsbeandefinition(beanname)) {
// not found -> check parent.
string nametolookup = originalbeanname(name);
if
(args !=
null
) {
// delegation to parent with explicit args.
return
(t) parentbeanfactory.getbean(nametolookup, args);
}
else
{
// no args -> delegate to standard getbean method.
return
parentbeanfactory.getbean(nametolookup, requiredtype);
}
}
if
(!typecheckonly) {
markbeanascreated(beanname);
}
try
{
//根据bean的名字取得beandefinition
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();
if
(dependson !=
null
) {
for
(string dep : dependson) {
if
(isdependent(beanname, dep)) {
throw
new
beancreationexception(mbd.getresourcedescription(), beanname,
"circular depends-on relationship between '"
+ beanname +
"' and '"
+ dep +
"'"
);
}
registerdependentbean(dep, beanname);
getbean(dep);
}
}
//通过调用createbean方法创建singleton bean实例
if
(mbd.issingleton()) {
sharedinstance = getsingleton(beanname,
new
objectfactory<object>() {
@override
public
object getobject()
throws
beansexception {
try
{
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.
destroysingleton(beanname);
throw
ex;
}
}
});
bean = getobjectforbeaninstance(sharedinstance, name, beanname, mbd);
}
//这里是创建prototype bean的地方
else
if
(mbd.isprototype()) {
// it's a prototype -> create a new instance.
object prototypeinstance =
null
;
try
{
beforeprototypecreation(beanname);
prototypeinstance = createbean(beanname, mbd, args);
}
finally
{
afterprototypecreation(beanname);
}
bean = getobjectforbeaninstance(prototypeinstance, name, beanname, mbd);
}
else
{
string scopename = mbd.getscope();
final
scope scope =
this
.scopes.get(scopename);
if
(scope ==
null
) {
throw
new
illegalstateexception(
"no scope registered for scope name '"
+ scopename +
"'"
);
}
try
{
object scopedinstance = scope.get(beanname,
new
objectfactory<object>() {
@override
public
object getobject()
throws
beansexception {
beforeprototypecreation(beanname);
try
{
return
createbean(beanname, mbd, args);
}
finally
{
afterprototypecreation(beanname);
}
}
});
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进行类型检查,如果没有问题,就返回这个新创建的bean,这个bean已经是包含了依赖关系的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;
}
|
依赖注入就是在这里被触发的.而依赖注入的发生是在容器中的beandefinition数据已经建立好的前提下进行的.虽然我们可以用最简单的方式来描述ioc容器,那就是视其为一个hashmap,但只能说这个hashmap是容器的最基本的数据结构,而不是ioc容器的全部. 。
关于这个依赖注入过程会在下面详解,图1.1可以看到依赖注入的大致过程. 。
图1.1 依赖注入的过程 。
getbean是依赖注入的起点,之后会调用abstractautowirecapablebeanfactory中的createbean来生产需要的bean,还对bean初始化进行了处理,比如实现了在beandefinition中的init-method属性定义,bean后置处理器等.下面通过createbean代码了解这个过程 。
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
|
@override
protected
object createbean(string beanname, rootbeandefinition mbd, object[] args)
throws
beancreationexception {
if
(logger.isdebugenabled()) {
logger.debug(
"creating instance of bean '"
+ beanname +
"'"
);
}
rootbeandefinition mbdtouse = mbd;
// make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved class
// which cannot be stored in the shared merged bean definition.
//这里判断需要创建的bean是否可以被实例化,这个类是否可以通过类加载器来载入
class
<?> resolvedclass = resolvebeanclass(mbd, beanname);
if
(resolvedclass !=
null
&& !mbd.hasbeanclass() && mbd.getbeanclassname() !=
null
) {
mbdtouse =
new
rootbeandefinition(mbd);
mbdtouse.setbeanclass(resolvedclass);
}
// prepare method overrides.
try
{
mbdtouse.preparemethodoverrides();
}
catch
(beandefinitionvalidationexception ex) {
throw
new
beandefinitionstoreexception(mbdtouse.getresourcedescription(),
beanname,
"validation of method overrides failed"
, ex);
}
try
{
// give beanpostprocessors a chance to return a proxy instead of the target bean instance.
//如果bean配置了postprocessor,那么这里返回的是一个proxy
object bean = resolvebeforeinstantiation(beanname, mbdtouse);
if
(bean !=
null
) {
return
bean;
}
}
catch
(throwable ex) {
throw
new
beancreationexception(mbdtouse.getresourcedescription(), beanname,
"beanpostprocessor before instantiation of bean failed"
, ex);
}
try
{
object beaninstance = docreatebean(beanname, mbdtouse, args);
if
(logger.isdebugenabled()) {
logger.debug(
"finished creating instance of bean '"
+ beanname +
"'"
);
}
return
beaninstance;
}
catch
(beancreationexception ex) {
// a previously detected exception with proper bean creation context already...
throw
ex;
}
catch
(implicitlyappearedsingletonexception ex) {
// an illegalstateexception to be communicated up to defaultsingletonbeanregistry...
throw
ex;
}
catch
(throwable ex) {
throw
new
beancreationexception(
mbdtouse.getresourcedescription(), beanname,
"unexpected exception during bean creation"
, ex);
}
}
//接着到docreate中去看看bean是怎样生成的
protected
object docreatebean(
final
string beanname,
final
rootbeandefinition mbd,
final
object[] args) {
// instantiate the bean.
//用来持有创建出来的bean对象
beanwrapper instancewrapper =
null
;
//如果是单例,则先把缓存中的同名bean清除
if
(mbd.issingleton()) {
instancewrapper =
this
.factorybeaninstancecache.remove(beanname);
}
//这里是创建bean的地方,由createbeaninstance来完成
if
(instancewrapper ==
null
) {
//根据指定bean使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化
instancewrapper = createbeaninstance(beanname, mbd, args);
}
final
object bean = (instancewrapper !=
null
? instancewrapper.getwrappedinstance() :
null
);
class
<?> beantype = (instancewrapper !=
null
? instancewrapper.getwrappedclass() :
null
);
// allow post-processors to modify the merged bean definition.
synchronized
(mbd.postprocessinglock) {
if
(!mbd.postprocessed) {
applymergedbeandefinitionpostprocessors(mbd, beantype, beanname);
mbd.postprocessed =
true
;
}
}
// eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like beanfactoryaware.
//是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
boolean
earlysingletonexposure = (mbd.issingleton() &&
this
.allowcircularreferences &&
issingletoncurrentlyincreation(beanname));
if
(earlysingletonexposure) {
if
(logger.isdebugenabled()) {
logger.debug(
"eagerly caching bean '"
+ beanname +
"' to allow for resolving potential circular references"
);
}
//为避免后期循环依赖,可以在bean初始化完成前将创建实例的objectfactory加入工厂
addsingletonfactory(beanname,
new
objectfactory<object>() {
@override
public
object getobject()
throws
beansexception {
//对bean再次依赖引用,主要应用smartinstantialiationaware beanpostprocessor,
//其中我们熟知的aop就是在这里将advice动态织入bean中,若无则直接返回bean,不做任何处理
return
getearlybeanreference(beanname, mbd, bean);
}
});
}
// initialize the bean instance.
//这里是对bean的初始化,依赖注入往往在这里发生,这个exposedobject在初始化处理完后悔返回作为依赖注入完成后的bean
object exposedobject = bean;
try
{
//对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,则会递归初始化依赖bean
populatebean(beanname, mbd, instancewrapper);
if
(exposedobject !=
null
) {
//调用初始化方法,比如init-method
exposedobject = initializebean(beanname, exposedobject, mbd);
}
}
catch
(throwable ex) {
if
(ex
instanceof
beancreationexception && beanname.equals(((beancreationexception) ex).getbeanname())) {
throw
(beancreationexception) ex;
}
else
{
throw
new
beancreationexception(mbd.getresourcedescription(), beanname,
"initialization of bean failed"
, ex);
}
}
if
(earlysingletonexposure) {
object earlysingletonreference = getsingleton(beanname,
false
);
// earlysingletonreference 只有在检测到有循环依赖的情况下才会非空
if
(earlysingletonreference !=
null
) {
if
(exposedobject == bean) {
//如果exposedobject 没有在初始化方法中被改变,也就是没有被增强
exposedobject = earlysingletonreference;
}
else
if
(!
this
.allowrawinjectiondespitewrapping && hasdependentbean(beanname)) {
string[] dependentbeans = getdependentbeans(beanname);
set<string> actualdependentbeans =
new
linkedhashset<string>(dependentbeans.length);
for
(string dependentbean : dependentbeans) {
//检测依赖
if
(!removesingletonifcreatedfortypecheckonly(dependentbean)) {
actualdependentbeans.add(dependentbean);
}
}
//因为bean创建后其所依赖的bean一定是已经创建的,actualdependentbeans非空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在循环依赖
if
(!actualdependentbeans.isempty()) {
throw
new
beancurrentlyincreationexception(beanname,
"bean with name '"
+ beanname +
"' has been injected into other beans ["
+
stringutils.collectiontocommadelimitedstring(actualdependentbeans) +
"] in its raw version as part of a circular reference, but has eventually been "
+
"wrapped. this means that said other beans do not use the final version of the "
+
"bean. this is often the result of over-eager type matching - consider using "
+
"'getbeannamesoftype' with the 'alloweagerinit' flag turned off, for example."
);
}
}
}
}
// register bean as disposable.
try
{
//根据scope注册bean
registerdisposablebeanifnecessary(beanname, bean, mbd);
}
catch
(beandefinitionvalidationexception ex) {
throw
new
beancreationexception(mbd.getresourcedescription(), beanname,
"invalid destruction signature"
, ex);
}
return
exposedobject;
}
|
依赖注入其实包括两个主要过程 。
我们从上可以看到与依赖注入关系特别密切的方法有 。
createbeaninstance 生成bean包含的java对象 。
populatebean. 处理对各种bean对象的属性进行处理的过程(即依赖关系处理的过程) 。
先来看 createbeaninstance源码 。
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
|
/**
* create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
* @param beanname the name of the bean
* @param mbd the bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a beanwrapper for the new instance
*/
protected
beanwrapper createbeaninstance(string beanname, rootbeandefinition mbd, object[] args) {
// make sure bean class is actually resolved at this point.
// 确认需要创建的bean实例的类可以实例化
class
<?> beanclass = resolvebeanclass(mbd, beanname);
if
(beanclass !=
null
&& !modifier.ispublic(beanclass.getmodifiers()) && !mbd.isnonpublicaccessallowed()) {
throw
new
beancreationexception(mbd.getresourcedescription(), beanname,
"bean class isn't public, and non-public access not allowed: "
+ beanclass.getname());
}
supplier<?> instancesupplier = mbd.getinstancesupplier();
if
(instancesupplier !=
null
) {
return
obtainfromsupplier(instancesupplier, beanname);
}
//若工厂方法非空,则使用工厂方法策略对bean进行实例化
if
(mbd.getfactorymethodname() !=
null
) {
return
instantiateusingfactorymethod(beanname, mbd, args);
}
// shortcut when re-creating the same bean...
boolean
resolved =
false
;
boolean
autowirenecessary =
false
;
if
(args ==
null
) {
synchronized
(mbd.constructorargumentlock) {
//一个类有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造函数或对应的工厂方法
if
(mbd.resolvedconstructororfactorymethod !=
null
) {
resolved =
true
;
autowirenecessary = mbd.constructorargumentsresolved;
}
}
}
//如果已经解析过则使用解析好的构造函数方法不需要再次锁定
if
(resolved) {
if
(autowirenecessary) {
//构造函数自动注入
return
autowireconstructor(beanname, mbd,
null
,
null
);
}
else
{
//使用默认构造函数构造
return
instantiatebean(beanname, mbd);
}
}
// need to determine the constructor...
// 使用构造函数对bean进行实例化
constructor<?>[] ctors = determineconstructorsfrombeanpostprocessors(beanclass, beanname);
if
(ctors !=
null
||
mbd.getresolvedautowiremode() == rootbeandefinition.autowire_constructor ||
mbd.hasconstructorargumentvalues() || !objectutils.isempty(args)) {
return
autowireconstructor(beanname, mbd, ctors, args);
}
// no special handling: simply use no-arg constructor.
//使用默认的构造函数对bean进行实例化
return
instantiatebean(beanname, mbd);
}
/**
* instantiate the given bean using its default constructor.
* @param beanname the name of the bean
* @param mbd the bean definition for the bean
* @return a beanwrapper for the new instance
*/
//最常见的实例化过程instantiatebean
protected
beanwrapper instantiatebean(
final
string beanname,
final
rootbeandefinition mbd) {
//使用默认的实例化策略对bean进行实例化,默认的实例化策略是
//cglibsubclassinginstantiationstrategy,也就是使用cglib实例化bean
try
{
object beaninstance;
final
beanfactory parent =
this
;
if
(system.getsecuritymanager() !=
null
) {
beaninstance = accesscontroller.doprivileged(
new
privilegedaction<object>() {
@override
public
object run() {
return
getinstantiationstrategy().instantiate(mbd, beanname, parent);
}
}, getaccesscontrolcontext());
}
else
{
beaninstance = getinstantiationstrategy().instantiate(mbd, beanname, parent);
}
beanwrapper bw =
new
beanwrapperimpl(beaninstance);
initbeanwrapper(bw);
return
bw;
}
catch
(throwable ex) {
throw
new
beancreationexception(
mbd.getresourcedescription(), beanname,
"instantiation of bean failed"
, ex);
}
}
|
这里使用了cglib对bean进行实例化.cglib是一个字节码生成器的类库,它提供了一系列的api来提供生成和转换java的字节码的功能. 。
在spring aop中也使用cglib对java的字节码进行增强.在ioc容器中,要了解怎样使用cglib来生成bean对象,需要看一下simpleinstantiationstrategy类.它是spring用来生成bean对象的默认类,它提供了两种实例化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
|
public
class
simpleinstantiationstrategy
implements
instantiationstrategy {
@override
public
object instantiate(rootbeandefinition bd, string beanname, beanfactory owner) {
// don't override the class with cglib if no overrides.
if
(bd.getmethodoverrides().isempty()) {
//这里取得指定的构造器或者生成对象的工厂方法来对bean进行实例化
constructor<?> constructortouse;
synchronized
(bd.constructorargumentlock) {
constructortouse = (constructor<?>) bd.resolvedconstructororfactorymethod;
if
(constructortouse ==
null
) {
final
class
<?> clazz = bd.getbeanclass();
if
(clazz.isinterface()) {
throw
new
beaninstantiationexception(clazz,
"specified class is an interface"
);
}
try
{
if
(system.getsecuritymanager() !=
null
) {
constructortouse = accesscontroller.doprivileged(
new
privilegedexceptionaction<constructor<?>>() {
@override
public
constructor<?> run()
throws
exception {
return
clazz.getdeclaredconstructor((
class
[])
null
);
}
});
}
else
{
constructortouse = clazz.getdeclaredconstructor((
class
[])
null
);
}
bd.resolvedconstructororfactorymethod = constructortouse;
}
catch
(throwable ex) {
throw
new
beaninstantiationexception(clazz,
"no default constructor found"
, ex);
}
}
}
//通过beanutils进行实例化,这个beanutils的实例化通过constructor来实例化bean,在beanutils中可以看到具体的调用ctor.newinstance(args)
return
beanutils.instantiateclass(constructortouse);
}
else
{
// 使用cglib来实例化对象
return
instantiatewithmethodinjection(bd, beanname, owner);
}
}
}
|
bean之间依赖关系的处理 。
依赖关系处理的入口是前面提到的populatebean方法.由于其中涉及的面太多,在这里就不贴代码了.简要介绍一下依赖关系处理的流程:在populatebean方法中.
首先取得在beandefinition中设置的property值,然后开始依赖注入的过程.
首先处理autowire的注入,可以byname或者是bytype,之后对属性进行注入.
接着需要对bean reference进行解析,在对managelist、manageset、managemap等进行解析完之后,就已经为依赖注入准备好了条件,这是真正把bean对象设置到它所依赖的另一个bean属性中去的地方,其中处理的属性是各种各样的.
依赖注入发生在beanwrapper的setpropertyvalues中,具体的完成却是在beanwrapper的子类beanwrapperimpl中实现的,它会完成bean的属性值的注入,其中包括对array的注入、对list等集合类以及对非集合类的域进行注入.
进过一系列的注入,这样就完成了对各种bean属性的依赖注入过程.
在bean的创建和对象依赖注入的过程中,需要依据beandefinition中的信息来递归地完成依赖注入.
从前面的几个递归过程中可以看到,这些递归都是以getbean为入口的.
一个递归是在上下文体系中查找需要的bean和创建bean的递归调用; 。
另一个递归是在依赖注入时,通过递归调用容器的getbean方法,得到当前bean的依赖bean,同时也触发对依赖bean的创建和注入.
在对bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层层地完成bean的创建和注入,直到最后完成当前bean的创建。有了这个顶层bean的创建和对它属性依赖注入的完成,意味着和当前bean相关的整个依赖链的注入液完成了.
在bean创建和依赖注入完成以后,在ioc容器中建立起一系列依靠依赖关系联系起来的bean,这个bean已经不再是简单的java对象了。该bean系列以及bean之间的依赖关系建立完成之后,通过ioc的相关接口方法,就可以非常方便地供上层应用使用了.
2. lazy-init属性和预实例化 。
在前面的refresh方法中,我们可以看到调用了finishbeanfactoryinitialization来对配置了lazy-init的bean进行处理.
其实在这个方法中,封装了对lazy-init属性的处理,实际的处理是在defaultlistablebeanfactory这个基本容器的preinstantiatesingleton方法中完成的。该方法对单例bean完成预实例化,这个预实例化的完成巧妙地委托给容器来实现。如果需要预实例化,那么就直接在这里采用getbean去触发依赖注入,与正常依赖注入的触发相比,只有触发的时间和场合不同。在这里,依赖注入发生在容器执行refresh的过程中,即ioc容器初始化的过程中,而不像一般的依赖注入一样发生在ioc容器初始化完成以后,第一次通过getbean想容器索要bean的时候.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://www.jianshu.com/p/08c8c7953289 。
最后此篇关于浅谈Spring IoC容器的依赖注入原理的文章就讲到这里了,如果你想了解更多关于浅谈Spring IoC容器的依赖注入原理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我尝试阅读有关 Spring BOM、Spring Boot 和 Spring IO 的文档。 但是没有说明,我们应该如何一起使用它们? 在我的项目中,我们已经有了自己的 Parent POM ,所以
我正在开发的很酷的企业应用程序正在转向 Spring。这对所有团队来说都是非常酷和令人兴奋的练习,但也是一个巨大的压力源。我们所做的是逐渐将遗留组件移至 Spring 上下文。现在我们有一个 huuu
我正在尝试使用 @Scheduled 运行 Spring 批处理作业注释如下: @Scheduled(cron = "* * * * * ?") public void launchMessageDi
我对这两个概念有点困惑。阅读 Spring 文档,我发现,例如。 bean 工厂是 Spring 容器。我还读到“ApplicationContext 是 BeanFactory 的完整超集”。但两者
我们有一个使用 Spring BlazeDS 集成的应用程序。到目前为止,我们一直在使用 Spring 和 Flex,它运行良好。我们现在还需要添加一些 Spring MVC Controller 。
假设我有一个类(class) Person带属性name和 age ,它可以像这样用 Spring 配置: 我想要一个自定义的 Spring 模式元素,这很容易做到,允许我在我的 Sp
如何在 Java 中以编程方式使用 Spring Data 创建 MongoDB 复合索引? 使用 MongoTemplate 我可以创建一个这样的索引:mongoTemplate.indexOps(
我想使用 spring-complex-task 执行我的应用程序,并且我已经构建了复杂的 spring-batch Flow Jobs,它执行得非常好。 你能解释一下spring批处理流作业与spr
我实现了 spring-boot 应用程序,现在我想将它用作非 spring 应用程序的库。 如何初始化 lib 类,以便 Autowiring 的依赖项按预期工作?显然,如果我使用“new”创建类实
我刚开始学习 spring cloud security,我有一个基本问题。它与 Spring Security 有何不同?我们是否需要在 spring boot 上构建我们的应用程序才能使用 spr
有很多人建议我使用 Spring Boot 而不是 Spring 来开发 REST Web 服务。我想知道这两者到底有什么区别? 最佳答案 总之 Spring Boot 减少了编写大量配置和样板代码的
您能向我解释一下如何使用 Spring 正确构建 Web 应用程序吗?我知道 Spring 框架的最新版本是 4.0.0.RELEASE,但是 Spring Security 的最新版本是 3.2.0
我如何才能知道作为 Spring Boot 应用程序的一部分加载的所有 bean 的名称?我想在 main 方法中有一些代码来打印服务器启动后加载的 bean 的详细信息。 最佳答案 如spring-
我有一个使用 Spring 3.1 构建的 RESTful API,也使用 Spring Security。我有一个 Web 应用程序,也是一个 Spring 3.1 MVC 应用程序。我计划让移动客
升级到 Spring 5 后,我在 Spring Rabbit 和 Spring AMQP 中遇到错误。 两者现在都设置为 1.5.6.RELEASE 有谁知道哪些版本应该与 Spring 5 兼容?
我现在已经使用 Spring Framework 3.0.5 和 Spring Security 3.0.5 多次了。我知道Spring框架使用DI和AOP。我还知道 Spring Security
我收到错误 Unable to Location NamespaceHandler when using context:annotation-config running (java -jar) 由
在 Spring 应用程序中嵌入唯一版本号的策略是什么? 我有一个使用 Spring Boot 和 Spring Web 的应用程序。 它已经足够成熟,我想对其进行版本控制并在运行时看到它显示在屏幕上
我正在使用 spring data jpa 进行持久化。如果存在多个具有相同名称的实体,是否有一种方法可以将一个实体标记为默认值。类似@Primary注解的东西用来解决多个bean的依赖问题 @Ent
我阅读了 Spring 框架的 DAOSupport 类。但是我无法理解这些 DAOSuport 类的优点。在 DAOSupport 类中,我们调用 getXXXTemplate() 方法来获取特定的
我是一名优秀的程序员,十分优秀!