在上節(jié)spring容器之創(chuàng)建bean實(shí)例中我們看了# createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)完成了bean的初始化,雖然那個(gè)方法有點(diǎn)長(zhǎng),但我們最后總結(jié)發(fā)現(xiàn),spring是通過(guò)不同的策略模式來(lái)完成bean的初始化如:
- 通過(guò)回調(diào)#obtainFromSupplier(final String beanName, final RootBeanDefinition mbd) 方法來(lái)初始化
- 通過(guò)工廠方法的方式:#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)
- 還有一種就是通過(guò)構(gòu)造函數(shù)自動(dòng)注入的方式:#autowireConstructor(final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs)來(lái)實(shí)現(xiàn)bean的初始化
- 最后一種是默認(rèn)構(gòu)造函數(shù)的方式:#instantiateBean(final String beanName, final RootBeanDefinition mbd)的方法來(lái)實(shí)現(xiàn)bean的初始化工作
關(guān)于前面的兩種我們已經(jīng)說(shuō)了,這里就不在重復(fù)了,我們來(lái)看后兩種:
通過(guò)構(gòu)造函數(shù)自動(dòng)注入的方式
AbstractAutowireCapableBeanFactory.java
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//準(zhǔn)備一個(gè)BeanWrapperImpl用于bean實(shí)例的封裝
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化bw
this.beanFactory.initBeanWrapper(bw);
//1.獲取constructorToUse argsHolderToUse和argsToUse參數(shù)
Constructor<?> constructorToUse = null;//所使用的的構(gòu)造函數(shù)
ArgumentsHolder argsHolderToUse = null;//構(gòu)造參數(shù)
Object[] argsToUse = null;
//2.通過(guò)explicitArgs參數(shù)來(lái)決定實(shí)例化bean所使用的構(gòu)造函數(shù)及構(gòu)造參數(shù)
//explicitArgs為通過(guò)getBean傳入的,如果在調(diào)用的過(guò)程中指定構(gòu)造函數(shù)和參數(shù)那么直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
//2.1.這里表示沒(méi)有指定那么會(huì)從配置文件中去解析獲取
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//嘗試著從緩存中獲取工廠方法或者構(gòu)造函數(shù)
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
//從緩存中獲取構(gòu)造參數(shù)
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
//從緩存中沒(méi)獲取到,則從原先準(zhǔn)備的構(gòu)造參數(shù)緩存中獲取
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
//2.2.如果緩存中
//解析保存在beanDefinition中的參數(shù)
//如給定方法的構(gòu)造函數(shù) A(int ,int ),則通過(guò)此方法后就會(huì)把配置文件中的("1","1")轉(zhuǎn)換為 (1,1)
//緩存中的值可能是原始值也有可能是最終值
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
//2.3.沒(méi)有被緩存
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
//如果chosenCtors沒(méi)有被傳入,那么獲取構(gòu)造函數(shù)
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
//2.4.使用默認(rèn)的構(gòu)造函數(shù)初始化bean實(shí)例
//因?yàn)檫@里構(gòu)造參數(shù)不存在
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
//封裝初始化之后的bean
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
//2.5.是否需要解析器
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
//用于承載解析后的構(gòu)造函數(shù)參數(shù)的值
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//獲取配置文件構(gòu)造參數(shù)
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//解析構(gòu)造參數(shù)
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//3.對(duì)構(gòu)造函數(shù)進(jìn)行排序
//public構(gòu)造函數(shù)優(yōu)先,非public次之
AutowireUtils.sortConstructors(candidates);
//最小參數(shù)的權(quán)重
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍歷candidates 獲取構(gòu)造函數(shù)的參數(shù)類型
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
// 如果已經(jīng)找到選用的構(gòu)造函數(shù)或者需要的參數(shù)個(gè)數(shù)小于當(dāng)前的構(gòu)造函數(shù)參數(shù)個(gè)數(shù),則終止。
//因?yàn)?,已?jīng)按照參數(shù)個(gè)數(shù)降序排列了
if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//這里表示參數(shù)的個(gè)數(shù)不相等,那么繼續(xù)
if (paramTypes.length < minNrOfArgs) {
continue;
}
//參數(shù)的持有者對(duì)象
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {
//獲取注解上的參數(shù)名稱
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
//獲取構(gòu)造參數(shù)的探索器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//通過(guò)探測(cè)器獲取參數(shù)名稱
paramNames = pnd.getParameterNames(candidate);
}
}
//根據(jù)bean的名稱和構(gòu)造參數(shù)以及構(gòu)造函數(shù)來(lái)創(chuàng)建參數(shù)持有者ArgumentsHolder對(duì)象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}//如果是UnsatisfiedDependencyException異常則添加到causes中
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
//resolvedValues為null的情況下
else {
// Explicit arguments given -> arguments length must match exactly.
//構(gòu)造函數(shù)沒(méi)有參數(shù)的情況下
if (paramTypes.length != explicitArgs.length) {
continue;
}
//通過(guò)explicitArgs來(lái)創(chuàng)建ArgumentsHolder
argsHolder = new ArgumentsHolder(explicitArgs);
}
//isLenientConstructorResolution主要是判斷解析構(gòu)造函數(shù)的時(shí)候是否以寬松模式還是嚴(yán)格模式
//嚴(yán)格模式:解析構(gòu)造函數(shù)時(shí),必須所有的都需要匹配,否則拋出異常
//寬松模式:使用具有"最接近的模式"進(jìn)行匹配
//typeDiffWeight:類型差異權(quán)重
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
//如果它代表著當(dāng)前最接近的匹配則選擇作為構(gòu)造函數(shù)
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
//類型差異權(quán)重等于參數(shù)最小權(quán)重,將constructorToUse進(jìn)行保存
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//沒(méi)有可以執(zhí)行的構(gòu)造器函數(shù)或工廠方法,直接拋UnsatisfiedDependencyException異常
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//4.將解析的參數(shù)進(jìn)行保存
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
//5.實(shí)例化bean并封裝在bw中
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
關(guān)于構(gòu)造函數(shù)創(chuàng)建bean實(shí)例的過(guò)程中,我們發(fā)現(xiàn)跟#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) 方法一樣,關(guān)于詳細(xì)部分這里不再深究可以去看我的上一篇文章,接下來(lái)我們看看一個(gè)重要的部分就是創(chuàng)建完的bean是如何完成初始化的過(guò)程.
初始化過(guò)程
在#autowireConstructor()方法的末尾我們看到的是最后將創(chuàng)建完的bean通過(guò)方法# instantiate(String beanName, RootBeanDefinition mb Constructor<?> constructorToUse, Object[] argsToUse)來(lái)實(shí)現(xiàn)的,跟蹤代碼發(fā)現(xiàn):
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
該方法我們?cè)谏掀恼轮兄v過(guò)了這里不再啰嗦,發(fā)現(xiàn)這里并不是真正的核心處理方法,接著看:
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
//判斷是否有方法需要重載
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
//設(shè)置訪問(wèn)權(quán)限
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
//1.通過(guò) BeanUtils直接使用構(gòu)造器對(duì)象實(shí)例化Bean對(duì)象
return BeanUtils.instantiateClass(ctor, args);
}
else {
//2初始化CGLB對(duì)象
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
在該方法中,首先設(shè)置對(duì)訪問(wèn)權(quán)限的設(shè)置,首先是通過(guò)構(gòu)造器來(lái)實(shí)例化bean對(duì)象
BeanUtils.java
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
//設(shè)置構(gòu)造器可訪問(wèn)的權(quán)限
ReflectionUtils.makeAccessible(ctor);
//通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
return KotlinDelegate.instantiateClass(ctor, args);
}
else {
//獲取構(gòu)造函數(shù)的參數(shù)類型
Class<?>[] parameterTypes = ctor.getParameterTypes();
Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
//初始化新的參數(shù)長(zhǎng)度
Object[] argsWithDefaultValues = new Object[args.length];
//循環(huán)處理構(gòu)造參數(shù)的類型
for (int i = 0 ; i < args.length; i++) {
if (args[i] == null) {
//如果參數(shù)是isPrimitive類型的,保存其對(duì)應(yīng)的值在argsWithDefaultValues數(shù)組中
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
//用來(lái)構(gòu)建實(shí)例的參數(shù)不為null時(shí)
else {
argsWithDefaultValues[i] = args[i];
}
}
//通過(guò)夠構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象
return ctor.newInstance(argsWithDefaultValues);
}
}
//對(duì)各種異常進(jìn)行封裝,統(tǒng)一拋出BeanInstantiationException異常
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}
上述方法主要是通過(guò)構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象,主要的區(qū)別在于:
- 如果我們傳入的構(gòu)造參數(shù)存在,則直接創(chuàng)建
- 反之是對(duì)構(gòu)造參數(shù)的解析獲取,最后利用反射和內(nèi)省機(jī)制來(lái)構(gòu)建bean實(shí)例
在2我們可以看到是初始化cglb實(shí)例,接著看:
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName,
BeanFactory owner, @Nullable Constructor<?> ctor, Object... args) {
throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}
該方法為空實(shí)現(xiàn),主要是由子類org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy 來(lái)實(shí)現(xiàn),具體來(lái)看代碼:
CglibSubclassingInstantiationStrategy.java
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
return instantiateWithMethodInjection(bd, beanName, owner, null);
}
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Constructor<?> ctor, Object... args) {
// Must generate CGLIB subclass...
//<>生成一個(gè)CGLB子類對(duì)象
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}
/**
* An inner class created for historical reasons to avoid external CGLIB dependency
* in Spring versions earlier than 3.2.
*/
private static class CglibSubclassCreator {
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}
上述為創(chuàng)建CGLB實(shí)例的過(guò)程,在<>處我們可以看到還是通過(guò)#instantiate(@Nullable Constructor<?> ctor, Object... args)方法來(lái)完成實(shí)例的初始化過(guò)程,代碼如下:
/**
* Create a new instance of a dynamically generated subclass implementing the
* required lookups.
* @param ctor constructor to use. If this is {@code null}, use the
* no-arg constructor (no parameterization, or Setter Injection)
* @param args arguments to use for the constructor.
* Ignored if the {@code ctor} parameter is {@code null}.
* @return new instance of the dynamically generated subclass
*/
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
//創(chuàng)建一個(gè)cglb的代理類
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
//如果當(dāng)前構(gòu)造器不存在,通過(guò)BeanUtils調(diào)用默認(rèn)構(gòu)造器來(lái)創(chuàng)建
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
//獲取代理對(duì)象的構(gòu)造器
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
//創(chuàng)建實(shí)例
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
在獲代碼中我們可以看到,創(chuàng)建CGLB對(duì)象的過(guò)程,首先是獲取代理對(duì)象,如果當(dāng)前構(gòu)造器不存在則則使用默認(rèn)無(wú)參的,最后完成bean的創(chuàng)建,這就是關(guān)于CGLB實(shí)例創(chuàng)建的過(guò)程
小結(jié)
關(guān)于#createBeanInstance()的過(guò)程,spring對(duì)于不同創(chuàng)建都會(huì)選擇其對(duì)應(yīng)的策略模式來(lái)完成,關(guān)于策略模式有以下幾種:
- 通過(guò)Supplier回調(diào)方式的方式來(lái)實(shí)現(xiàn)bean的創(chuàng)建
- 通過(guò)工廠方法來(lái)完成bean的創(chuàng)建
- 通過(guò)構(gòu)造器自動(dòng)注入的方式來(lái)完成bean的創(chuàng)建
- 最后一種是通過(guò)默認(rèn)構(gòu)造器的方式
在以上4中的策略模式中,其中工廠方法和構(gòu)造器自動(dòng)注入的方式最為復(fù)雜,簡(jiǎn)友們可以仔細(xì)的看看,哈哈哈,代碼有點(diǎn)長(zhǎng)哦!其兩者的方式很接近,當(dāng)然我們?cè)谧詈笱苌隽薈GLiB實(shí)例的創(chuàng)建的過(guò)程,發(fā)現(xiàn)spring是通過(guò)#bd.hasMethodOverrides()來(lái)判斷是否有覆蓋的方法,如果有則只能通過(guò)cglib的方式來(lái)實(shí)例化,反之利用反射的方式來(lái)創(chuàng)建.
關(guān)于createBeanInstance()的詳細(xì)拆分就到這里了