首先,我們在3.1 spring5原始碼系列--迴圈依賴 之 手寫程式碼模擬spring迴圈依賴 中手寫了迴圈依賴的實現. 這個實現就是模擬的spring的迴圈依賴. 目的是為了更容易理解spring原始碼.
下面我們就進入正題, 看看spring的迴圈依賴原始碼.
一、getBean整體流程
目標很明確了, 就是要看看spring如何解決迴圈依賴的.
程式碼入口是refresh()#finishBeanFactoryInitialization(beanFactory);
二、拆解研究流程中的每一步
呼叫方法beanFactory.preInstantiateSingletons();例項化剩餘的單例bean. 為什麼是剩餘的?很顯然我們在上面已經例項化一部分了.比如配置類, postProcessor等.
2.1 入口
1 @Override
2 public void preInstantiateSingletons() throws BeansException {
3 if (logger.isTraceEnabled()) {
4 logger.trace("Pre-instantiating singletons in " + this);
5 }
6
7
8 // 獲取容器中所有bean定義的名字
9 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
10
11 // Trigger initialization of all non-lazy singleton beans...
12 /**
13 * 第一步: 迴圈bean定義的name
14 */
15 for (String beanName : beanNames) {
16 // 獲取bean定義
17 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
18 // 生產bean定義的條件: 不是抽象的, 是單例的, 不是懶載入的. 符合這個標準的, 最後才會呼叫getBean()生產bean
19 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
20 // 這裡判斷是不是工廠bean, 這裡和BeanFactory不是一個意思, 判斷當前這個bean是否實現了beanFactory的介面
21 if (isFactoryBean(beanName)) {
22 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
23 if (bean instanceof FactoryBean) {
24 final FactoryBean<?> factory = (FactoryBean<?>) bean;
25 boolean isEagerInit;
26 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
27 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
28 ((SmartFactoryBean<?>) factory)::isEagerInit,
29 getAccessControlContext());
30 }
31 else {
32 isEagerInit = (factory instanceof SmartFactoryBean &&
33 ((SmartFactoryBean<?>) factory).isEagerInit());
34 }
35 if (isEagerInit) {
36 // 獲取bean
37 getBean(beanName);
38 }
39 }
40 }
41 else {
// 第二步: 呼叫bean定義
42 getBean(beanName);
43 }
44 }
45 }
46
47 // Trigger post-initialization callback for all applicable beans...
48 /**
49 * 迴圈bean定義的name
50 */
51 for (String beanName : beanNames) {
52 // 從快取中得到例項instance
53 Object singletonInstance = getSingleton(beanName);
54 if (singletonInstance instanceof SmartInitializingSingleton) {
55 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
56 if (System.getSecurityManager() != null) {
57 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
58 smartSingleton.afterSingletonsInstantiated();
59 return null;
60 }, getAccessControlContext());
61 }
62 else {
63 smartSingleton.afterSingletonsInstantiated();
64 }
65 }
66 }
67 }
首先, 迴圈bean定義, 這和我們模擬spring迴圈的第一步是一樣的.
第二步: 判斷從BeanDefinitionMap中取出來的這個bean是否滿足生產bean的條件
我們注意程式碼註釋中, 生產bean定義的條件: 不是抽象的, 是單例的, 不是懶載入的. 符合這個標準的, 最後才會呼叫getBean()生產bean
然後:呼叫getBean()
到目前為止,我們完成了上圖原始碼圖的第一部分:
2.2 建立bean前的準備工作
接下來看看getBean().doGetBean()方法
1 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
2 @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
3
4 // 第一步: 轉換bean name. 在這裡傳入進來的name可能是別名, 也有可能是工廠bean的name, 所以在這裡進行一個轉換
5 final String beanName = transformedBeanName(name);
6 Object bean;
7
8 // Eagerly check singleton cache for manually registered singletons.
9 // 第二步: 嘗試去快取中獲取物件, 如果沒有獲取到就建立bean
10 Object sharedInstance = getSingleton(beanName);
11 if (sharedInstance != null && args == null) {
12 if (logger.isTraceEnabled()) {
13 //判斷當前類是否是正在建立中
14 if (isSingletonCurrentlyInCreation(beanName)) {
15 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
16 "' that is not fully initialized yet - a consequence of a circular reference");
17 }
18 else {
19 logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
20 }
21 }
22 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
23 }
24
25 else {
26 // Fail if we're already creating this bean instance:
27 // We're assumably within a circular reference.
28 /**
29 * 判斷當前的bean是不是多例, 如果是這丟擲異常
30 *
31 * 判斷當前這個bean是不是多例bean. 如果配置了@Scope("prototype") 就表示這是一個多例的bean
32 * spring 只能解決單例物件的setter注入的迴圈依賴, 不能解決構造器注入
33 *
34 * 如果是多例的bean, 當前正在建立bean, 也會丟擲異常---這也是迴圈依賴的問題
35 */
36 if (isPrototypeCurrentlyInCreation(beanName)) {
37 throw new BeanCurrentlyInCreationException(beanName);
38 }
39
40 /**
41 * 下面這段程式碼是關於子父容器的, 只有spring mvc繼承自spring, 才會有子父容器的問題.
42 */
43 // Check if bean definition exists in this factory.
44 BeanFactory parentBeanFactory = getParentBeanFactory();
45 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
46 // Not found -> check parent.
47 String nameToLookup = originalBeanName(name);
48 if (parentBeanFactory instanceof AbstractBeanFactory) {
49 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
50 nameToLookup, requiredType, args, typeCheckOnly);
51 }
52 else if (args != null) {
53 // Delegation to parent with explicit args.
54 return (T) parentBeanFactory.getBean(nameToLookup, args);
55 }
56 else if (requiredType != null) {
57 // No args -> delegate to standard getBean method.
58 return parentBeanFactory.getBean(nameToLookup, requiredType);
59 }
60 else {
61 return (T) parentBeanFactory.getBean(nameToLookup);
62 }
63 }
64
65 /**
66 * 方法引數typeCheckOnly是用來判斷#getBean()方法時, 表示是否為僅僅進行型別檢查,
67 * 如果不僅僅做型別檢查, 而是建立bean物件, 則需要呼叫#markBeanAsCreated(String name)
68 *
69 */
70 if (!typeCheckOnly) {
71 markBeanAsCreated(beanName);
72 }
73
74 try {
75 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
76 checkMergedBeanDefinition(mbd, beanName, args);
77
78 // Guarantee initialization of beans that the current bean depends on.
79 /**
80 * 現在有兩個bean1, bean2 , 載入的時候呼叫的是bean1, bean2. 但如果我們想要bean2優先載入, 就使用@DependOn註解
81 * 用來解析帶有dependOn註解的類
82 */
83 String[] dependsOn = mbd.getDependsOn();
84 if (dependsOn != null) {
85 for (String dep : dependsOn) {
86 if (isDependent(beanName, dep)) {
87 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
88 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
89 }
90 registerDependentBean(dep, beanName);
91 try {
92 getBean(dep);
93 }
94 catch (NoSuchBeanDefinitionException ex) {
95 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
96 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
97 }
98 }
99 }
100
101 // Create bean instance.
102 /**
103 * 第三步: 建立單例bean例項
104 */
105 if (mbd.isSingleton()) { // 處理單例bean
106 /**
107 * 這裡getSingleton()和上面的getSigleton不一樣, 上面的是從一級快取中拿.
108 * 這個getSingleton()就辦了一件事: 將bean設定為正在建立的狀態. 這個狀態很重要, 如果出現迴圈依賴, 發現bean正在建立, 就不會再建立了
109 */
110 sharedInstance = getSingleton(beanName, () -> {
111 try {
112 return createBean(beanName, mbd, args);
113 }
114 catch (BeansException ex) {
115 // Explicitly remove instance from singleton cache: It might have been put there
116 // eagerly by the creation process, to allow for circular reference resolution.
117 // Also remove any beans that received a temporary reference to the bean.
118 destroySingleton(beanName);
119 throw ex;
120 }
121 });
122 // 得到bean例項物件
123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124 }
125
126 else if (mbd.isPrototype()) { // 處理多例bean
127 // It's a prototype -> create a new instance.
128 Object prototypeInstance = null;
129 try {
130 // 當前正在建立多例bean
131 beforePrototypeCreation(beanName);
132 // 執行建立bean
133 prototypeInstance = createBean(beanName, mbd, args);
134 }
135 finally {
136 afterPrototypeCreation(beanName);
137 }
138 // 獲取bean例項物件
139 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140 }
141
142 else { // 處理其他型別的bean
143 String scopeName = mbd.getScope();
144 final Scope scope = this.scopes.get(scopeName);
145 if (scope == null) {
146 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147 }
148 try {
149 Object scopedInstance = scope.get(beanName, () -> {
150 beforePrototypeCreation(beanName);
151 try {
152 return createBean(beanName, mbd, args);
153 }
154 finally {
155 afterPrototypeCreation(beanName);
156 }
157 });
158 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159 }
160 catch (IllegalStateException ex) {
161 throw new BeanCreationException(beanName,
162 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164 ex);
165 }
166 }
167 }
168 catch (BeansException ex) {
169 cleanupAfterBeanCreationFailure(beanName);
170 throw ex;
171 }
172 }
在這裡, 首先從快取中獲取bean, 看快取中是否已經存在了
Object sharedInstance = getSingleton(beanName);
然後, 如果快取中已經存在了,那麼久直接取出來. 程式碼如下:
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
//判斷當前bean是否是正在建立中(單例bean)
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
如果是空, 就說明是第一次建立, 執行else的部分
首先, 判斷是否是正在建立的多例bean, 如果是正在建立的多例bean, 就丟擲異常,
已經是正在建立了, 說明這至少是第二次了, 這裡處理的是單例bean的迴圈依賴, 不處理多例bean的迴圈依賴, 所以丟擲異常
對應的程式碼是這一句
// Fail if we're already creating this bean instance:
27 // We're assumably within a circular reference.
28 /**
29 * 判斷當前的bean是不是多例, 如果是這丟擲異常
30 *
31 * 判斷當前這個bean是不是多例bean. 如果配置了@Scope("prototype") 就表示這是一個多例的bean
32 * spring 只能解決單例物件的setter注入的迴圈依賴, 不能解決構造器注入
33 *
34 * 如果是多例的bean, 當前正在建立bean, 也會丟擲異常---這也是迴圈依賴的問題
35 */
36 if (isPrototypeCurrentlyInCreation(beanName)) {
37 throw new BeanCurrentlyInCreationException(beanName);
38 }
那麼, 接下來就是首次建立bean. 首次建立的bean有三種情況:
第一種, 這個bean是單例的.
第二種, 這個bean是多例的.
第三種. 其他型別
對應的程式碼就是這一塊. 有行號, 可以和上面一一對應上
// Create bean instance.
102 /**
103 * 第三步: 建立單例bean例項
104 */
105 if (mbd.isSingleton()) { // 處理單例bean
106 /**
107 * 這裡getSingleton()和上面的getSigleton不一樣, 上面的是從一級快取中拿.
108 * 這個getSingleton()就辦了一件事: 將bean設定為正在建立的狀態. 這個狀態很重要, 如果出現迴圈依賴, 發現bean正在建立, 就不會再建立了
109 */
110 sharedInstance = getSingleton(beanName, () -> {
111 try {
112 return createBean(beanName, mbd, args);
113 }
114 catch (BeansException ex) {
115 // Explicitly remove instance from singleton cache: It might have been put there
116 // eagerly by the creation process, to allow for circular reference resolution.
117 // Also remove any beans that received a temporary reference to the bean.
118 destroySingleton(beanName);
119 throw ex;
120 }
121 });
122 // 得到bean例項物件
123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124 }
125
126 else if (mbd.isPrototype()) { // 處理多例bean
127 // It's a prototype -> create a new instance.
128 Object prototypeInstance = null;
129 try {
130 // 當前正在建立多例bean
131 beforePrototypeCreation(beanName);
132 // 執行建立bean
133 prototypeInstance = createBean(beanName, mbd, args);
134 }
135 finally {
136 afterPrototypeCreation(beanName);
137 }
138 // 獲取bean例項物件
139 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140 }
141
142 else { // 處理其他型別的bean
143 String scopeName = mbd.getScope();
144 final Scope scope = this.scopes.get(scopeName);
145 if (scope == null) {
146 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147 }
148 try {
149 Object scopedInstance = scope.get(beanName, () -> {
150 beforePrototypeCreation(beanName);
151 try {
152 return createBean(beanName, mbd, args);
153 }
154 finally {
155 afterPrototypeCreation(beanName);
156 }
157 });
158 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159 }
160 catch (IllegalStateException ex) {
161 throw new BeanCreationException(beanName,
162 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164 ex);
165 }
166 }
我們的重點研究物件是單例bean. 所以,重點看單例bean的實現
105 if (mbd.isSingleton()) { // 處理單例bean
106 /**
107 * 這裡getSingleton()和上面的getSigleton不一樣, 上面的是從一級快取中拿.
108 * 這個getSingleton()就辦了一件事: 將bean設定為正在建立的狀態. 這個狀態很重要, 如果出現迴圈依賴, 發現bean正在建立, 就不會再建立了
109 */
110 sharedInstance = getSingleton(beanName, () -> {
111 try {
112 return createBean(beanName, mbd, args);
113 }
114 catch (BeansException ex) {
115 // Explicitly remove instance from singleton cache: It might have been put there
116 // eagerly by the creation process, to allow for circular reference resolution.
117 // Also remove any beans that received a temporary reference to the bean.
118 destroySingleton(beanName);
119 throw ex;
120 }
121 });
122 // 得到bean例項物件
123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124 }
這裡的重點是呼叫了getSingleton(beanName, FactoryObject); FactoryObject是一個介面. 定義了一個鉤子方法getObject().
這個介面在這裡這是進行了定義, 並不會執行. 什麼時候執行呢? 後面呼叫的時候執行.
下面來看看getSingleton()方法, 鉤子方法也是在這裡被呼叫的.
1 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
2 Assert.notNull(beanName, "Bean name must not be null");
3 synchronized (this.singletonObjects) {
4 // 第一步: 從一級快取中獲取單例物件
5 Object singletonObject = this.singletonObjects.get(beanName);
6 if (singletonObject == null) {
7 if (this.singletonsCurrentlyInDestruction) {
8 throw new BeanCreationNotAllowedException(beanName,
9 "Singleton bean creation not allowed while singletons of this factory are in destruction " +
10 "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
11 }
12 if (logger.isDebugEnabled()) {
13 logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
14 }
15 // 第二步: 將bean新增到singletonsCurrentlyInCreation中, 表示bean正在建立
16 beforeSingletonCreation(beanName);
17 boolean newSingleton = false;
18 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
19 if (recordSuppressedExceptions) {
20 this.suppressedExceptions = new LinkedHashSet<>();
21 }
22 try {
23 // 第三步: 這裡呼叫getObject()鉤子方法, 就會回撥匿名函式, 呼叫singletonFactory的createBean()
24 singletonObject = singletonFactory.getObject();
25 newSingleton = true;
26 }
27 catch (IllegalStateException ex) {
28 // Has the singleton object implicitly appeared in the meantime ->
29 // if yes, proceed with it since the exception indicates that state.
30 singletonObject = this.singletonObjects.get(beanName);
31 if (singletonObject == null) {
32 throw ex;
33 }
34 }
35 catch (BeanCreationException ex) {
36 if (recordSuppressedExceptions) {
37 for (Exception suppressedException : this.suppressedExceptions) {
38 ex.addRelatedCause(suppressedException);
39 }
40 }
41 throw ex;
42 }
43 finally {
44 if (recordSuppressedExceptions) {
45 this.suppressedExceptions = null;
46 }
47 afterSingletonCreation(beanName);
48 }
49 if (newSingleton) {
50 addSingleton(beanName, singletonObject);
51 }
52 }
53 return singletonObject;
54 }
55 }
這裡是呼叫getBean().
第一步: 去一級快取中取成熟的單例bean. 如果拿到了, 就直接返回. 如果沒拿到. 那麼執行建立.
第二步: 在建立之前, 先把這個bean放入到正在建立的單例bean集合中. 標記這個bean正在建立中
第三步: 就是呼叫鉤子方法getObject()了. 這個方法的方法體是在上面定義的. 其內容是去建立例項
sharedInstance = getSingleton(beanName, () -> {
try {
// 這裡定義了一個鉤子函式. 此時只是定義, 並不執行. 在真正需要建立bean的地方才會執行
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;
}
});
這裡的程式碼邏輯是完成了建立之前的邏輯
2.3 建立bean
下面看看建立bean的過程
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/**
* 第一步: 例項化
* 這裡面的呼叫鏈非常深, 後面再看
* bean例項化有兩種方式
* 1. 使用反射: 使用反射也有兩種方式,
* a. 通過無參建構函式 (預設的方式)
* 從beanDefinition中可以得到beanClass,
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* clazz.newInstance();
* 這樣就可以例項化bean了
*
* b. 通過有參函式.
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* Constractor con = class.getConstractor(args....)
* con.newInstance();
*
* 2. 使用工廠
* 我們使用@Bean的方式, 就是使用的工廠模式, 自己控制例項化過程
*
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 這裡使用了裝飾器的設計模式
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 允許後置處理器修改已經合併的beanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
/**
* 快取單例bean到三級快取中, 以防止迴圈依賴
* 判斷是否是早期引用的bean, 如果是, 則允許提前暴露引用
*
* 判斷是否能夠早起暴露的條件
* 1. 是單例
* 2. 允許迴圈依賴
* 3. 正在建立的bean
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 把我們的早期物件包裝成一個singletonFactory物件, 該物件提供了getObject()方法, 把靜態的bean放到三級快取中去了.
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 第二步:填充屬性, 給屬性賦值(呼叫set方法) 這裡也是呼叫的後置處理器
populateBean(beanName, mbd, instanceWrapper);
// 第三步: 初始化.
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) {
// 去快取中獲取到我們的物件 由於傳遞的allowEarlyReference是false, 要求只能在一級二級快取中取
// 正常的普通的bean(不存在迴圈依賴的bean) 建立的過程中, 不會把三級快取提升到二級快取中.
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
首先, 例項化bean, 例項化的方式有兩種. 一種是通過反射, 另一種是通過動態代理
/**
* 第一步: 例項化
* 這裡面的呼叫鏈非常深, 後面再看
* bean例項化有兩種方式
* 1. 使用反射: 使用反射也有兩種方式,
* a. 通過無參建構函式 (預設的方式)
* 從beanDefinition中可以得到beanClass,
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* clazz.newInstance();
* 這樣就可以例項化bean了
*
* b. 通過有參函式.
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* Constractor con = class.getConstractor(args....)
* con.newInstance();
*
* 2. 使用工廠
* 我們使用@Bean的方式, 就是使用的工廠模式, 自己控制例項化過程
*
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
判斷是否是早期暴露的bean. 滿足早期暴露的bean的三個條件是
1. 是單例的
2. 允許迴圈依賴
3. bean已經是處在正在建立中的行列了.
/* 判斷是否能夠早起暴露的條件
* 1. 是單例
* 2. 允許迴圈依賴
* 3. 正在建立的bean
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
建立bean的第二步: 屬性賦值
// 第二步:填充屬性, 給屬性賦值(呼叫set方法) 這裡也是呼叫的後置處理器 populateBean(beanName, mbd, instanceWrapper);
在這裡會判斷, 是否帶有@Autowired的屬性. 分為兩種一種是Name,一種是Type
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 判斷屬性是否有Autowired註解
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// Autowired是根據名字或者根據型別
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
......
}
如果按照名字注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 呼叫getBean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("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");
}
}
}
}
會再次呼叫getBean方法. 構建bean. 這是就有可能出現迴圈依賴了.
按型別注入也是一樣的.
只是解析bean的方式不同.
建立bean的第三步: 初始化
// 第三步: 初始化. exposedObject = initializeBean(beanName, exposedObject, mbd);
在初始化bean的時候, 會呼叫很多的aware. 還會呼叫init-method方法. 以及bean的後置處理器.
第四步:刪除例項化和靜態方法在快取中的資料
/**
* 初始化完成以後, 判斷是否是早期的物件
* 是迴圈依賴. 才會走進這裡來
*/
if (earlySingletonExposure) {
// 去快取中獲取到我們的物件 由於傳遞的allowEarlyReference是false, 要求只能在一級二級快取中取
// 正常的普通的bean(不存在迴圈依賴的bean) 建立的過程中, 不會把三級快取提升到二級快取中.
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
removeSingletonIfCreatedForTypeCheckOnly呼叫方法, 刪除快取.
這既是getBean()整個的過程. 中間還有很多細節, 沒有往裡面深入的看, 因為spring程式碼非常的深, 看的太深就忘了我們的目標了. 結合之前手寫的spring迴圈依賴的思想看, 還是可以看得懂的.
三. 接下來有幾個問題
問題1: 為什麼需要二級快取和三級快取?
二級快取用來存放早期的bean, 也就是沒有被屬性賦值和初始化的bean
三級快取的主要作用是用來解耦. 解耦後非同步呼叫, 三級快取中儲存的是鉤子方法,也就是一個介面。在使用的時候呼叫bean的後置處理器
問題2:有沒有解決建構函式的迴圈依賴
答案是沒有. 因為建構函式是在例項化的時候構建的. 這個時候bean都還沒有建立, 所以沒有辦法處理迴圈依賴.如果出現建構函式的迴圈依賴, 是會直接報錯的..
問題3:有沒有解決多例下的迴圈依賴
也是沒有的, 因為我們會判斷, 如果是多例, 那麼會丟擲異常
1 /**
2 * 第二步: 判斷當前bean是否是正在建立中的多例bean, 如果是就丟擲異常
3 *
4 * 2. 判斷當前這個bean是不是多例bean. 如果配置了@Scope("prototype") 就表示這是一個多例的bean
5 * spring 只能解決單例物件的setter注入的迴圈依賴, 不能解決構造器注入
6 *
7 * 如果是多例的bean, 當前正在建立bean, 也會丟擲異常---這也是迴圈依賴的問題
8 */
9 if (isPrototypeCurrentlyInCreation(beanName)) {
10 throw new BeanCurrentlyInCreationException(beanName);
11 }