一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 淺談Spring IoC容器的依賴注入原理

淺談Spring IoC容器的依賴注入原理

2021-04-09 11:51芥末無疆sss Java教程

這篇文章主要介紹了淺談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可以看到依賴注入的大致過程.

淺談Spring IoC容器的依賴注入原理

圖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;
  }

依賴注入其實包括兩個主要過程

  1. 生產bea所包含的java對象
  2. bean對象生成之后,把這些bean對象的依賴關系設置好

我們從上可以看到與依賴注入關系特別密切的方法有

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. 通過beanutils,使用了java的反射功能
  2. 通過cglib來生成
?
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

延伸 · 閱讀

精彩推薦
  • Java教程Spring 6.0 將停止支持 Freemarker 和 JSP

    Spring 6.0 將停止支持 Freemarker 和 JSP

    Spring Framework 6.0 第一個里程碑版本已經發布,目前已經可以從Spring Repo獲取。這里有一些新變更我們可以提前了解一下。...

    碼農小胖哥12642021-12-31
  • Java教程mybatis批量新增、刪除、查詢和修改方式

    mybatis批量新增、刪除、查詢和修改方式

    這篇文章主要介紹了mybatis批量新增、刪除、查詢和修改方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教...

    xuforeverlove7492022-01-24
  • Java教程Spring Cloud Gateway 如何修改HTTP響應信息

    Spring Cloud Gateway 如何修改HTTP響應信息

    這篇文章主要介紹了Spring Cloud Gateway 修改HTTP響應信息的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教...

    帷幄庸者13712021-10-13
  • Java教程二進制中1的個數

    二進制中1的個數

    這篇文章介紹了二進制中1的個數,有需要的朋友可以參考一下 ...

    java之家2662019-10-15
  • Java教程mybatis調用存儲過程的實例代碼

    mybatis調用存儲過程的實例代碼

    這篇文章主要介紹了mybatis調用存儲過程的實例,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    動力節點11732021-01-25
  • Java教程Java開發常見異常及解決辦法詳解

    Java開發常見異常及解決辦法詳解

    這篇文章主要介紹了java程序常見異常及處理匯總,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考...

    cutercorley12252021-12-18
  • Java教程淺談sql_@SelectProvider及使用注意說明

    淺談sql_@SelectProvider及使用注意說明

    這篇文章主要介紹了sql_@SelectProvider及使用注意說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教...

    icecoola_6892021-11-04
  • Java教程淺談java 中equals和==的區別

    淺談java 中equals和==的區別

    這篇文章主要介紹了java 中equals和==的區別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小...

    獨特潤許多人5982021-07-21
主站蜘蛛池模板: 亚洲社区在线观看 | 拔插拔插8x8x海外华人免费视频 | 欧美日韩精品一区二区三区高清视频 | 国产精品合集久久久久青苹果 | segou视频在线观看 | 婷婷九月| 免费看隐私男生网站 | 农村妇女野外性生话免费视频 | 欧美在线视频一区 | 日本一区二区视频免费播放 | 成人精品视频 成人影院 | 久久精品热在线观看30 | 久久足恋网 | 精品一区二区三区高清免费观看 | 成人免费播放器 | 欧美怡红院视频一区二区三区 | 高h全肉动漫在线观看免费 高h辣h双处全是肉军婚 | 91在线亚洲综合在线 | gay男强壮军人chinese | 太粗 好紧 使劲舒服 | 欧美日韩精 | 亚洲qvod图片区电影 | 日本艳鉧动漫1~6在线观看 | 毛片免费视频观看 | 四虎影院免费在线播放 | 秋霞鲁丝影院久久人人综合 | 国产精品亚洲精品日韩已满 | 美女脱一光二净的视频 | 午夜亚洲WWW湿好爽 午夜想想爱午夜剧场 | 青青青视频免费观看 | 日韩欧美色图 | 四虎在线最新永久免费 | avtt在线播放 | 免费理伦片在线观看全网站 | 岛国在线播放v片免费 | 青青草精品 | 操老妇 | 亚洲精品在线免费看 | 夫妇野外交换激情 | 欧美老骚 | 色色色色色色网 |