Spring Bean生命周期之Bean的實例化詳解
前言
上一節(jié)說到了BeanDefinition的合并過程,這節(jié)該說Bean的實例化過程了。根據(jù)AbstractAutowireCapableBeanFactory#createBean源碼邏輯 可將實例化過程分為實例化前階段、實例化過程、實例化后階段。
實例化前階段
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//省略無關(guān)代碼
try {
// 這里就是我們分析的重點了 ??
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//?? 注意這個邏輯:如果postProcessBeforeInstantiation方法返回非null 則將返回值作為創(chuàng)建的Bean。并中斷正常的創(chuàng)建流程
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
//省略異常信息
}
try {
//真正創(chuàng)建Bean的邏輯 實例化Bean對象,為Bean屬性賦值等,這里暫不展開
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
//省略日志輸出
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {//省略異常信息
}
resolveBeforeInstantiation這個方法在BeanPostProcessor淺析 這一節(jié)分析過了 這里不再具體展開了。
如果InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法返回null,那么將不會中斷正常Bean創(chuàng)建過程。
下面就來到的Bean實例化部分了。
實例化階段
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//解析BeanClass,在BeanDefinition中類信息是以字符串形式展現(xiàn),這里解析到字符串后 會將其加載為Class
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());
}
//如果設(shè)置了 Supplier 回調(diào),則使用給定的回調(diào)方法初始化策略,通過獲取Supplier#get得到實例化對象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果工廠方法不為空,則使用工廠方法初始化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
//加鎖
synchronized (mbd.constructorArgumentLock) {
//條件成立 說明構(gòu)造函數(shù)或FactoryMethod已經(jīng)被解析并被緩存,可直接利用構(gòu)造函數(shù)解析
//與后面的SimpleInstantiationStrategy#instantiate呼應(yīng)
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已經(jīng)被解析過
if (resolved) {
//條件成立 使用構(gòu)造函數(shù)注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
//使用默認(rèn)構(gòu)造函數(shù)解析
return instantiateBean(beanName, mbd);
}
}
// 使用SmartInstantiationAwareBeanPostProcessor 找到候選的構(gòu)造函數(shù) 用于注入
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// AutowireMode==AUTOWIRE_CONSTRUCTOR 條件成立 說明使用基于構(gòu)造函數(shù)的注入方式 (默認(rèn)是AUTOWIRE_NO,需要動態(tài)檢測)
// mbd.hasConstructorArgumentValues() 條件成立 說明構(gòu)造函數(shù)中擁有參數(shù)
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//基于構(gòu)造函數(shù)自動注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 如果mbd中配置了構(gòu)造函數(shù) 則使用它進(jìn)行注入
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 使用默認(rèn)構(gòu)造函數(shù)實例化
return instantiateBean(beanName, mbd);
}
上面將doCreateBean精簡一下,只暴露出我們比較關(guān)系的部分。一目了然,Bean的實例化過程就藏在createBeanInstance方法中。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//解析BeanClass,在BeanDefinition中類信息是以字符串形式展現(xiàn),這里解析到字符串后 會將其加載為Class
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());
}
//如果設(shè)置了 Supplier 回調(diào),則使用給定的回調(diào)方法初始化策略,通過獲取Supplier#get得到實例化對象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果工廠方法不為空,則使用工廠方法初始化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
//加鎖
synchronized (mbd.constructorArgumentLock) {
//條件成立 說明構(gòu)造函數(shù)或FactoryMethod已經(jīng)被解析并被緩存,可直接利用構(gòu)造函數(shù)解析
//與后面的SimpleInstantiationStrategy#instantiate呼應(yīng)
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已經(jīng)被解析過
if (resolved) {
//條件成立 使用構(gòu)造函數(shù)注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
//使用默認(rèn)構(gòu)造函數(shù)解析
return instantiateBean(beanName, mbd);
}
}
// 使用SmartInstantiationAwareBeanPostProcessor 找到候選的構(gòu)造函數(shù) 用于注入
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// AutowireMode==AUTOWIRE_CONSTRUCTOR 條件成立 說明使用基于構(gòu)造函數(shù)的注入方式 (默認(rèn)是AUTOWIRE_NO,需要動態(tài)檢測)
// mbd.hasConstructorArgumentValues() 條件成立 說明構(gòu)造函數(shù)中擁有參數(shù)
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//基于構(gòu)造函數(shù)自動注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 如果mbd中配置了構(gòu)造函數(shù) 則使用它進(jìn)行注入
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 使用默認(rèn)構(gòu)造函數(shù)實例化
return instantiateBean(beanName, mbd);
}
分析了上面的源碼之后,我們試著總結(jié)一下上面代碼主要完成的事情:
1、如果mbd配置了instanceSupplier回調(diào),則使用instanceSupplier去初始化BeanDefinition
2、如果mbd配置了工廠方法,則使用工廠方法區(qū)初始化BeanDefinition
3、實例化BeanDefinition
- 如果mbd已經(jīng)被解析過了,則根據(jù)緩存 選擇使用有參構(gòu)造函數(shù)注入還是默認(rèn)構(gòu)造函數(shù)注入
- 如果mbd沒有被解析過,找到mbd中候選的構(gòu)造函數(shù)(一個類可能有多個構(gòu)造函數(shù)),再根據(jù)一些限定條件 選擇是基于有參構(gòu)造函數(shù)初始化還是默認(rèn)構(gòu)造函數(shù)初始化
針對第1點,其實就是lambda8 supplier接口的使用,不再介紹。
針對第3點,其實就是通過反射機制 創(chuàng)建實例對象,最終調(diào)用了SimpleInstantiationStrategy#instantiate方法
針對第2點 舉例說明下 工廠方法與靜態(tài)工廠生成Bean的兩種形式,再來展開說下instantiateUsingFactoryMethod源碼。
配置Xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="peopleFactory" class="com.wojiushiwo.factorymethod.PeopleFactory"/>
<!--實例方法-->
<bean id="instanceMethod" factory-bean="peopleFactory" factory-method="createPeople"/>
<!--靜態(tài)方法-->
<bean id="staticFactoryMethod" class="com.wojiushiwo.factorymethod.People" factory-method="createPeople"/>
</beans>
//實體對象
@Data
public class People implements Serializable {
private String name;
private Integer age;
public People() {
}
public static People createPeople() {
People people = new People();
people.setAge(18);
people.setName("我就是我");
return people;
}
}
//People工廠類
public class PeopleFactory {
public People createPeople() {
return People.createPeople();
}
}
public class FactoryMethodDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("META-INF/spring.xml");
context.refresh();
People people = (People) context.getBean("staticFactoryMethod");
System.out.println(people);
People people = (People) context.getBean("instanceMethod");
System.out.println(people);
context.close();
}
}
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
//獲取FactoryBeanName,實例方法與靜態(tài)工廠方法的區(qū)別就在于有沒有FactoryBeanName
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
//如果存在FactoryBeanName,則說明是實例方法
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
//獲取當(dāng)前factoryBeanName名稱的Bean
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
//獲取工廠類Class
factoryClass = factoryBean.getClass();
//標(biāo)記為非靜態(tài)
isStatic = false;
}
else {
// 走到這里,說明是靜態(tài)工廠方法
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
//factoryBean設(shè)置為null
factoryBean = null;
//獲取工廠類Class,這里使用BeanDefinition作為其工廠類
factoryClass = mbd.getBeanClass();
//標(biāo)記為非靜態(tài)
isStatic = true;
}
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//explicitArgs 這個是getBean方法傳遞過來的,一般為null
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
//加鎖
synchronized (mbd.constructorArgumentLock) {
//獲取被解析的工廠方法
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
//條件成立 說明工廠方法已經(jīng)被解析過了,并存到了mbd中緩存起來了
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
if (factoryMethodToUse == null || argsToUse == null) {
//獲取工廠類
factoryClass = ClassUtils.getUserClass(factoryClass);
//獲取類中的方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List<Method> candidateList = new ArrayList<>();
for (Method candidate : rawCandidates) {
//如果方法修飾符包含static,并且方法名稱是配置的FactoryMethod,則添加到候選集合中
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateList.add(candidate);
}
}
//如果候選集合有1個元素 并且BeanDefinition中未設(shè)置構(gòu)造參數(shù) (explicitArgs一般都為null )
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
//獲取方法
Method uniqueCandidate = candidateList.get(0);
//如果方法參數(shù)為空
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
//將下面這些全緩存到mbd中,下次直接用(與createBeanInstance方法呼應(yīng)上了)
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
//實例化bd,設(shè)置到BeanWrapper中
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
//程序走到這里 大概率是BeanDefinition中設(shè)置了構(gòu)造參數(shù)
Method[] candidates = candidateList.toArray(new Method[0]);
//按照修飾符及方法參數(shù) 進(jìn)行排序
AutowireUtils.sortFactoryMethods(candidates);
ConstructorArgumentValues resolvedValues = null;
//是否構(gòu)造函數(shù)注入
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
//最小參數(shù)數(shù)量 默認(rèn)是0
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//走到這里 說明explicitArgs未被設(shè)置參數(shù)
//如果bd設(shè)置了構(gòu)造參數(shù),則從bd中解析參數(shù)
if (mbd.hasConstructorArgumentValues()) {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//得到解析的最小參數(shù)數(shù)量
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
LinkedList<UnsatisfiedDependencyException> causes = null;
//下面主要是推斷參數(shù)、FactoryMethod,代碼比較長 就先不分析了
for (Method candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
if (explicitArgs != null) {
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// Resolved constructor arguments: type conversion and/or autowiring necessary.
try {
String[] paramNames = null;
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
if (factoryMethodToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
}
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
//拋出異常
}
else if (void.class == factoryMethodToUse.getReturnType()) {
//拋出異常
}
else if (ambiguousFactoryMethods != null) {
//拋出異常
}
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
Assert.state(argsToUse != null, "Unresolved factory method arguments");
//實例化bd 設(shè)置到BeanWrapper中
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
至此經(jīng)過createBeanInstance方法 就為我們創(chuàng)建了一個實例對象,但是現(xiàn)在這個對象屬性還未被賦值。
實例化后階段
實例對象創(chuàng)建之后,就來到了對象屬性賦值過程了,我們大致看一下populateBean方法,觀察下InstantiationAwareBeanPostProcessor對屬性賦值過程的影響
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//省略無關(guān)代碼
boolean continueWithPropertyPopulation = true;
//條件一 synthetic默認(rèn)值是false 一般都會成立
//條件二 成立的話 說明存在InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//在BeanPostProcessor淺析中分析到此方法時說過,若Bean實例化后回調(diào)不返回true 則對屬性賦值過程產(chǎn)生影響。以下代碼就是說明
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//ibp.postProcessAfterInstantiation=false時 屬性賦值過程終止
if (!continueWithPropertyPopulation) {
return;
}
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
SpringCloud LoadBalancer自定義負(fù)載均衡器使用解析
LoadBalancerClient 是 SpringCloud 提供的一種負(fù)載均衡客戶端,Ribbon 負(fù)載均衡組件內(nèi)部也是集成了 LoadBalancerClient 來實現(xiàn)負(fù)載均衡,本文給大家深入解析 LoadBalancerClient 接口源碼,感興趣的朋友跟隨小編一起看看吧2023-04-04
利用Spring Cloud Zuul實現(xiàn)動態(tài)路由示例代碼
Spring Cloud Zuul路由是微服務(wù)架構(gòu)的不可或缺的一部分,提供動態(tài)路由,監(jiān)控,彈性,安全等的邊緣服務(wù)。下面這篇文章主要給大家介紹了關(guān)于利用Spring Cloud Zuul實現(xiàn)動態(tài)路由的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-09-09
Java 反轉(zhuǎn)帶頭結(jié)點的單鏈表并顯示輸出的實現(xiàn)過程
這篇文章主要介紹了Java 反轉(zhuǎn)帶頭結(jié)點的單鏈表并顯示輸出,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-11-11
springboot整合Quartz實現(xiàn)動態(tài)配置定時任務(wù)的方法
本篇文章主要介紹了springboot整合Quartz實現(xiàn)動態(tài)配置定時任務(wù)的方法,非常具有實用價值,需要的朋友可以參考下2017-10-10
SpringBoot中的MongoTemplate的各種條件查詢示例詳解
這篇文章主要介紹了SpringBoot中的MongoTemplate的各種條件查詢示例詳解,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借價值,需要的朋友參考下吧2024-01-01

