javascript
【死磕 Spring】—– IOC 之 Factory 实例化 bean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析 bean,將 bean 類名解析為 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());
}
// 如果存在 Supplier 回調(diào),則使用給定的回調(diào)方法初始化策略
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) {
// constructorArgumentLock 構(gòu)造函數(shù)的常用鎖
synchronized (mbd.constructorArgumentLock) {
// 如果已緩存的解析的構(gòu)造函數(shù)或者工廠方法不為空,則可以利用構(gòu)造函數(shù)解析
// 因?yàn)樾枰鶕?jù)參數(shù)確認(rèn)到底使用哪個(gè)構(gòu)造函數(shù),該過(guò)程比較消耗性能,所有采用緩存機(jī)制
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 已經(jīng)解析好了,直接注入即可
if (resolved) {
// 自動(dòng)注入,調(diào)用構(gòu)造函數(shù)自動(dòng)注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默認(rèn)構(gòu)造函數(shù)構(gòu)造
return instantiateBean(beanName, mbd);
}
}
// 確定解析的構(gòu)造函數(shù)
// 主要是檢查已經(jīng)注冊(cè)的 SmartInstantiationAwareBeanPostProcessor
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 構(gòu)造函數(shù)自動(dòng)注入
return autowireConstructor(beanName, mbd, ctors, args);
}
//使用默認(rèn)構(gòu)造函數(shù)注入
return instantiateBean(beanName, mbd);
}
實(shí)例化 bean 是一個(gè)復(fù)雜的過(guò)程,其主要的邏輯為:
如果存在 Supplier 回調(diào),則調(diào)用 obtainFromSupplier() 進(jìn)行初始化
如果存在工廠方法,則使用工廠方法進(jìn)行初始化
首先判斷緩存,如果緩存中存在,即已經(jīng)解析過(guò)了,則直接使用已經(jīng)解析了的,根據(jù) constructorArgumentsResolved 參數(shù)來(lái)判斷是使用構(gòu)造函數(shù)自動(dòng)注入還是默認(rèn)構(gòu)造函數(shù)
如果緩存中沒(méi)有,則需要先確定到底使用哪個(gè)構(gòu)造函數(shù)來(lái)完成解析工作,因?yàn)橐粋€(gè)類有多個(gè)構(gòu)造函數(shù),每個(gè)構(gòu)造函數(shù)都有不同的構(gòu)造參數(shù),所以需要根據(jù)參數(shù)來(lái)鎖定構(gòu)造函數(shù)并完成初始化,如果存在參數(shù)則使用相應(yīng)的帶有參數(shù)的構(gòu)造函數(shù),否則使用默認(rèn)構(gòu)造函數(shù)。
下面就上面四種情況做分別說(shuō)明。
obtainFromSupplier()
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
首先從 BeanDefinition 中獲取 Supplier,如果不為空,則調(diào)用 obtainFromSupplier() 。那么 Supplier 是什么呢?在這之前也沒(méi)有提到過(guò)這個(gè)字段。
public interface Supplier<T> {
T get();
}
Supplier 接口僅有一個(gè)功能性的 get(),該方法會(huì)返回一個(gè) T 類型的對(duì)象,有點(diǎn)兒類似工廠方法。這個(gè)接口有什么作用?用于指定創(chuàng)建 bean 的回調(diào),如果我們?cè)O(shè)置了這樣的回調(diào),那么其他的構(gòu)造器或者工廠方法都會(huì)沒(méi)有用。在什么設(shè)置該參數(shù)呢?Spring 提供了相應(yīng)的 setter 方法,如下:
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
在構(gòu)造 BeanDefinition 的時(shí)候設(shè)置了該值,如下(以 RootBeanDefinition 為例):
public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {
super();
setBeanClass(beanClass);
setScope(scope);
setInstanceSupplier(instanceSupplier);
}
如果設(shè)置了 instanceSupplier 則調(diào)用 obtainFromSupplier() 完成 bean 的初始化,如下:
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
Object instance;
try {
// 調(diào)用 Supplier 的 get(),返回一個(gè)對(duì)象
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
// 根據(jù)對(duì)象構(gòu)造 BeanWrapper 對(duì)象
BeanWrapper bw = new BeanWrapperImpl(instance);
// 初始化 BeanWrapper
initBeanWrapper(bw);
return bw;
}
代碼很簡(jiǎn)單,調(diào)用 調(diào)用 Supplier 的 get() 方法,獲得一個(gè) bean 實(shí)例對(duì)象,然后根據(jù)該實(shí)例對(duì)象構(gòu)造一個(gè) BeanWrapper 對(duì)象 bw,最后初始化該對(duì)象。有關(guān)于 BeanWrapper 后面專門出文講解。
instantiateUsingFactoryMethod()
如果存在工廠方法,則調(diào)用 instantiateUsingFactoryMethod() 完成 bean 的初始化工作(方法實(shí)現(xiàn)比較長(zhǎng),細(xì)節(jié)比較復(fù)雜,各位就硬著頭皮看吧)。
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
構(gòu)造一個(gè) ConstructorResolver 對(duì)象,然后調(diào)用其 instantiateUsingFactoryMethod() 方法。ConstructorResolver 是構(gòu)造方法或者工廠類初始化 bean 的委托類。
public BeanWrapper instantiateUsingFactoryMethod(
final String beanName, final RootBeanDefinition mbd, @Nullable final Object[] explicitArgs) {
// 構(gòu)造 BeanWrapperImpl 對(duì)象
BeanWrapperImpl bw = new BeanWrapperImpl();
// 初始化 BeanWrapperImpl
// 向BeanWrapper對(duì)象中添加 ConversionService 對(duì)象和屬性編輯器 PropertyEditor 對(duì)象
//
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
// 工廠名不為空
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 獲取工廠實(shí)例
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// 工廠名為空,則其可能是一個(gè)靜態(tài)工廠
// 靜態(tài)工廠創(chuàng)建bean,必須要提供工廠的全類名
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
// 工廠方法
Method factoryMethodToUse = null;
ConstructorResolver.ArgumentsHolder argsHolderToUse = null;
// 參數(shù)
Object[] argsToUse = null;
// 工廠方法的參數(shù)
// 如果指定了構(gòu)造參數(shù)則直接使用
// 在調(diào)用 getBean 方法的時(shí)候指定了方法參數(shù)
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
// 沒(méi)有指定,則嘗試從配置文件中解析
Object[] argsToResolve = null;
// 首先嘗試從緩存中獲取
synchronized (mbd.constructorArgumentLock) {
// 獲取緩存中的構(gòu)造函數(shù)或者工廠方法
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// 獲取緩存中的構(gòu)造參數(shù)
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 獲取緩存中的構(gòu)造函數(shù)參數(shù)的包可見(jiàn)字段
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 緩存中存在,則解析存儲(chǔ)在 BeanDefinition 中的參數(shù)
// 如給定方法的構(gòu)造函數(shù) A(int ,int ),則通過(guò)此方法后就會(huì)把配置文件中的("1","1")轉(zhuǎn)換為 (1,1)
// 緩存中的值可能是原始值也有可能是最終值
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
}
}
//
if (factoryMethodToUse == null || argsToUse == null) {
// 獲取工廠方法的類全名稱
factoryClass = ClassUtils.getUserClass(factoryClass);
// 獲取所有待定方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
// 檢索所有方法,這里是對(duì)方法進(jìn)行過(guò)濾
List<Method> candidateSet = new ArrayList<>();
for (Method candidate : rawCandidates) {
// 如果有static 且為工廠方法,則添加到 candidateSet 中
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateSet.add(candidate);
}
}
Method[] candidates = candidateSet.toArray(new Method[0]);
// 排序構(gòu)造函數(shù)
// public 構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量降序,非public 構(gòu)造函數(shù)參數(shù)數(shù)量降序
AutowireUtils.sortFactoryMethods(candidates);
// 用于承載解析后的構(gòu)造函數(shù)參數(shù)的值
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// getBean() 沒(méi)有傳遞參數(shù),則需要解析保存在 BeanDefinition 構(gòu)造函數(shù)中指定的參數(shù)
if (mbd.hasConstructorArgumentValues()) {
// 構(gòu)造函數(shù)的參數(shù)
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析構(gòu)造函數(shù)的參數(shù)
// 將該 bean 的構(gòu)造函數(shù)參數(shù)解析為 resolvedValues 對(duì)象,其中會(huì)涉及到其他 bean
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Method candidate : candidates) {
// 方法體的參數(shù)
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
// 保存參數(shù)的對(duì)象
ArgumentsHolder argsHolder;
// getBean()傳遞了參數(shù)
if (explicitArgs != null){
// 顯示給定參數(shù),參數(shù)長(zhǎng)度必須完全匹配
if (paramTypes.length != explicitArgs.length) {
continue;
}
// 根據(jù)參數(shù)創(chuàng)建參數(shù)持有者
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// 為提供參數(shù),解析構(gòu)造參數(shù)
try {
String[] paramNames = null;
// 獲取 ParameterNameDiscoverer 對(duì)象
// ParameterNameDiscoverer 是用于解析方法和構(gòu)造函數(shù)的參數(shù)名稱的接口,為參數(shù)名稱探測(cè)器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 獲取指定構(gòu)造函數(shù)的參數(shù)名稱
paramNames = pnd.getParameterNames(candidate);
}
// 在已經(jīng)解析的構(gòu)造函數(shù)參數(shù)值的情況下,創(chuàng)建一個(gè)參數(shù)持有者對(duì)象
argsHolder = createArgumentArray(
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
}
catch (UnsatisfiedDependencyException ex) {
if (this.beanFactory.logger.isTraceEnabled()) {
this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
"] of bean '" + beanName + "': " + ex);
}
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
// 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));
// 代表最接近的類型匹配,則選擇作為構(gòu)造函數(shù)
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// 如果具有相同參數(shù)數(shù)量的方法具有相同的類型差異權(quán)重,則收集此類型選項(xiàng)
// 但是,僅在非寬松構(gòu)造函數(shù)解析模式下執(zhí)行該檢查,并顯式忽略重寫(xiě)方法(具有相同的參數(shù)簽名)
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
// 查找到多個(gè)可匹配的方法
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
// 沒(méi)有可執(zhí)行的工廠方法,拋出異常
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<ConstructorArgumentValues.ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ConstructorArgumentValues.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);
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"No matching factory method found: " +
(mbd.getFactoryBeanName() != null ?
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() +
"': needs to have a non-void return type!");
}
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}
if (explicitArgs == null && argsHolderToUse != null) {
// 將解析的構(gòu)造函數(shù)加入緩存
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
try {
// 實(shí)例化 bean
Object beanInstance;
if (System.getSecurityManager() != null) {
final Object fb = factoryBean;
final Method factoryMethod = factoryMethodToUse;
final Object[] args = argsToUse;
// 通過(guò)執(zhí)行工廠方法來(lái)創(chuàng)建bean示例
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args),
beanFactory.getAccessControlContext());
}
else {
// 通過(guò)執(zhí)行工廠方法來(lái)創(chuàng)建bean示例
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
}
// 包裝為 BeanWraper 對(duì)象
bw.setBeanInstance(beanInstance);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex);
}
}
instantiateUsingFactoryMethod() 方法體實(shí)在是太大了,處理細(xì)節(jié)感覺(jué)很復(fù)雜,LZ是硬著頭皮看完的,中間斷斷續(xù)續(xù)的。吐槽這里的代碼風(fēng)格,完全不符合我們前面看的 Spring 代碼風(fēng)格。Spring 的一貫做法是將一個(gè)復(fù)雜邏輯進(jìn)行拆分,分為多個(gè)細(xì)小的模塊進(jìn)行嵌套,每個(gè)模塊負(fù)責(zé)一部分功能,模塊與模塊之間層層嵌套,上一層一般都是對(duì)下一層的總結(jié)和概括,這樣就會(huì)使得每一層的邏輯變得清晰易懂。
回歸到上面的方法體,雖然代碼體量大,但是總體我們還是可看清楚這個(gè)方法要做的事情。一句話概括就是:確定工廠對(duì)象,然后獲取構(gòu)造函數(shù)和構(gòu)造參數(shù),最后調(diào)用 InstantiationStrategy 對(duì)象的 instantiate() 來(lái)創(chuàng)建 bean 實(shí)例。下面我們就這個(gè)句概括的話進(jìn)行拆分并詳細(xì)說(shuō)明。
確定工廠對(duì)象
首先獲取工廠方法名,若工廠方法名不為空,則調(diào)用 beanFactory.getBean() 獲取工廠對(duì)象,若為空,則可能為一個(gè)靜態(tài)工廠,對(duì)于靜態(tài)工廠則必須提供工廠類的全類名,同時(shí)設(shè)置 factoryBean=null
構(gòu)造參數(shù)確認(rèn)
工廠對(duì)象確定后,則是確認(rèn)構(gòu)造參數(shù)。構(gòu)造參數(shù)的確認(rèn)主要分為三種情況:explicitArgs 參數(shù)、緩存中獲取、配置文件中解析。
explicitArgs 參數(shù)
explicitArgs 參數(shù)是我們調(diào)用 getBean() 時(shí)傳遞景來(lái),一般該參數(shù),該參數(shù)就是用于初始化 bean 時(shí)所傳遞的參數(shù),如果該參數(shù)不為空,則可以確定構(gòu)造函數(shù)的參數(shù)就是它了。
緩存中獲取
在該方法的最后,我們會(huì)發(fā)現(xiàn)這樣一段代碼: argsHolderToUse.storeCache(mbd,factoryMethodToUse) ,這段代碼主要是將構(gòu)造函數(shù)、構(gòu)造參數(shù)保存到緩存中,如下:
public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
mbd.constructorArgumentsResolved = true;
if (this.resolveNecessary) {
mbd.preparedConstructorArguments = this.preparedArguments;
}
else {
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
其中涉及到的幾個(gè)參數(shù) constructorArgumentLock、resolvedConstructorOrFactoryMethod、constructorArgumentsResolved、resolvedConstructorArguments。這些參數(shù)都是跟構(gòu)造函數(shù)、構(gòu)造函數(shù)緩存有關(guān)的。
constructorArgumentLock:構(gòu)造函數(shù)的緩存鎖
resolvedConstructorOrFactoryMethod:緩存已經(jīng)解析的構(gòu)造函數(shù)或者工廠方法
constructorArgumentsResolved:標(biāo)記字段,標(biāo)記構(gòu)造函數(shù)、參數(shù)已經(jīng)解析了。默認(rèn)為false
resolvedConstructorArguments:緩存已經(jīng)解析的構(gòu)造函數(shù)參數(shù),包可見(jiàn)字段
所以從緩存中獲取就是提取這幾個(gè)參數(shù)的值,如下:
synchronized (mbd.constructorArgumentLock) {
// 獲取緩存中的構(gòu)造函數(shù)或者工廠方法
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// 獲取緩存中的構(gòu)造參數(shù)
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 獲取緩存中的構(gòu)造函數(shù)參數(shù)的包可見(jiàn)字段
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
如果緩存中存在構(gòu)造參數(shù),則需要調(diào)用 resolvePreparedArguments() 方法進(jìn)行轉(zhuǎn)換,因?yàn)榫彺嬷械闹涤锌赡苁亲罱K值也有可能不是最終值,比如我們構(gòu)造函數(shù)中的類型為 Integer 類型的 1 ,但是原始的參數(shù)類型有可能是 String 類型的 1 ,所以即便是從緩存中得到了構(gòu)造參數(shù)也需要經(jīng)過(guò)一番的類型轉(zhuǎn)換確保參數(shù)類型完全對(duì)應(yīng)。
配置文件中解析
即沒(méi)有通過(guò)傳遞參數(shù)的方式傳遞構(gòu)造參數(shù),緩存中也沒(méi)有,那就只能通過(guò)解析配置文件獲取構(gòu)造參數(shù)了。
在 bean 解析類的博文中我們了解了,配置文件中的信息都會(huì)轉(zhuǎn)換到 BeanDefinition 實(shí)例對(duì)象中,所以配置文件中的參數(shù)可以直接通過(guò) BeanDefinition 對(duì)象獲取。代碼如下:
if (mbd.hasConstructorArgumentValues()) {
// 構(gòu)造函數(shù)的參數(shù)
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析構(gòu)造函數(shù)的參數(shù)
// 將該 bean 的構(gòu)造函數(shù)參數(shù)解析為 resolvedValues 對(duì)象,其中會(huì)涉及到其他 bean
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
通過(guò) BeanDefinition 的 getConstructorArgumentValues() 就可以獲取構(gòu)造信息了,有了構(gòu)造信息就可以獲取相關(guān)的參數(shù)值信息了,獲取的參數(shù)信息包括直接值和引用,這一步驟的處理交由 resolveConstructorArguments()完成,該方法會(huì)將構(gòu)造參數(shù)信息解析為 resolvedValues 對(duì)象 并返回解析到的參數(shù)個(gè)數(shù)。
構(gòu)造函數(shù)
確定構(gòu)造參數(shù)后,下一步則是確定構(gòu)造函數(shù)。第一步則是通過(guò) getCandidateMethods() 獲取所有的構(gòu)造方法,同時(shí)對(duì)構(gòu)造方法進(jìn)行刷選,然后在對(duì)其進(jìn)行排序處理( AutowireUtils.sortFactoryMethods(candidates)),排序的主要目的是為了能夠更加方便的找到匹配的構(gòu)造函數(shù),因?yàn)闃?gòu)造函數(shù)的確認(rèn)是根據(jù)參數(shù)個(gè)數(shù)確認(rèn)的。排序的規(guī)則是:public 構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量降序、非 public 構(gòu)造參數(shù)數(shù)量降序。
通過(guò)迭代 candidates(包含了所有要匹配的構(gòu)造函數(shù))的方式,一次比較其參數(shù),如果顯示提供了參數(shù)(explicitArgs != null),則直接比較兩者是否相等,如果相等則表示找到了,否則繼續(xù)比較。如果沒(méi)有顯示提供參數(shù),則需要獲取 ParameterNameDiscoverer 對(duì)象,該對(duì)象為參數(shù)名稱探測(cè)器,主要用于發(fā)現(xiàn)方法和構(gòu)造函數(shù)的參數(shù)名稱。
將參數(shù)包裝成 ArgumentsHolder 對(duì)象,該對(duì)象用于保存參數(shù),我們稱之為參數(shù)持有者。當(dāng)將對(duì)象包裝成 ArgumentsHolder 對(duì)象后,我們就可以通過(guò)它來(lái)進(jìn)行構(gòu)造函數(shù)匹配,匹配分為嚴(yán)格模式和寬松模式。
嚴(yán)格模式:解析構(gòu)造函數(shù)時(shí),必須所有參數(shù)都需要匹配,否則拋出異常
寬松模式:使用具有"最接近的模式"進(jìn)行匹配
判斷的依據(jù)是根據(jù) BeanDefinition 的 isLenientConstructorResolution 屬性(該參數(shù)是我們?cè)跇?gòu)造 AbstractBeanDefinition 對(duì)象是傳遞的)來(lái)獲取類型差異權(quán)重(typeDiffWeight) 的。如果 typeDiffWeight<minTypeDiffWeight ,則代表“最接近的模式”,選擇其作為構(gòu)造函數(shù),否則只有兩者具有相同的參數(shù)數(shù)量且類型差異權(quán)重相等才會(huì)納入考慮范圍。
至此,構(gòu)造函數(shù)已經(jīng)確認(rèn)了。
創(chuàng)建 bean 實(shí)例
工廠對(duì)象、構(gòu)造函數(shù)、構(gòu)造參數(shù)都已經(jīng)確認(rèn)了,則最后一步就是調(diào)用 InstantiationStrategy 對(duì)象的 instantiate() 來(lái)創(chuàng)建 bean 實(shí)例,如下:
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
// 執(zhí)行工廠方法,并返回實(shí)例
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
// 省略一波 catch
}
instantiate() 最核心的部分就是利用 Java 反射執(zhí)行工廠方法并返回創(chuàng)建好的實(shí)例,也就是這段代碼:
Object result = factoryMethod.invoke(factoryBean, args);
到這里 instantiateUsingFactoryMethod() 已經(jīng)分析完畢了,這里 LZ 有些題外話需要說(shuō)下,看源碼真心是一個(gè)痛苦的過(guò)程,尤其是復(fù)雜的源碼,比如這個(gè)方法我看了三天才弄清楚點(diǎn)皮毛,當(dāng)然這里跟 LZ 的智商有些關(guān)系(智商捉急 ┭┮﹏┭┮),寫(xiě)這篇博客也花了五天時(shí)間才寫(xiě)完(最后截稿日為:2018.08.10 01:23:49),所以每一個(gè)堅(jiān)持寫(xiě)博客的都是折翼的天使,值得各位尊敬
createBeanInstance() 還有兩個(gè)重要方法 autowireConstructor() 和 instantiateBean() ,由于篇幅問(wèn)題,所以將這兩個(gè)方法放在下篇博客分析。敬請(qǐng)期待!!!
原文發(fā)布時(shí)間為:2018-10-31
本文作者:Java技術(shù)驛站
本文來(lái)自云棲社區(qū)合作伙伴“Java技術(shù)驛站”,了解相關(guān)信息可以關(guān)注“Java技術(shù)驛站”。
總結(jié)
以上是生活随笔為你收集整理的【死磕 Spring】—– IOC 之 Factory 实例化 bean的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python---pandas.merg
- 下一篇: 自定义过滤器