本文是針對Srping的BeanFactory.getBean來進行源碼解析,若是您是第一次看請先看一下XMLBeanFactory解析:blog.csdn.net/qq_30257149…,能夠更好的理解Spring的註冊原理,本篇博客是跟源碼一步步看spring怎麼實現getBean源碼,Spring版本爲5.X,源碼已經在每一行上加了註釋,方便讀者學習。html
GItHub:github.com/lantaoGitHu…java
package org.springframework.lantao;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class XmlBeanFactoryTest {
public static void main(String[] args) {
ClassPathResource classPathResource = new ClassPathResource("spring-bean.xml");
BeanFactory beanFactory = new XmlBeanFactory(classPathResource);
UserBean userBean = (UserBean) beanFactory.getBean("userBean");
System.out.println(userBean.getName());
}
}複製代碼
XMLBeanFactory解析就很少說了,若是沒看過的能夠去看我上一篇文章,這裏直接看BeanFactory.getBean()git
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//獲取實例名字
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 檢查單例緩存中是否存在實例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
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 {
// Fail if we're already creating this bean instance: // We're assumably within a circular reference.
// 原型 循環引用 拋異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
// 將指定的bean標記爲已經建立(或即將建立)。這容許bean工廠優化其緩存,以便重複建立指定的bean
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 建立bean實例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
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);
}
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, () -> { 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. if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }複製代碼
doGetBean的源碼比較長,那它都作了哪些事情呢:github
1:轉換對應的beanname,可能有不少人不理解,傳入進來的不就應該是beanName嘛,其實傳入的多是BeanFactory,也多是別名,若是是BeanFactory,就要去除它的修飾符,好比傳入進來的&aa,就要轉換成aa,但若是傳入進來的是別名,就要取alias對應的最終的beanName,例如別名A指向了B的bean則返回B的beanName,若是別名A指向了別名B,別名B指向了C,則要返回C的BeanName;spring
2:檢查單例中是否存在實例,會先從緩存中獲取,下面會詳細講解;緩存
3:判斷原型實例是否存在循環依賴,好比A中有B,B中有A,這種狀況只有單例模式纔會嘗試去建立,由於單例模式會提前包曝光實例,存在緩存中,原型模式是不容許的,會拋出類正在建立異常;bash
4:經過父BeanFactory獲取bean;app
5:將指定的bean標記爲已經建立(或即將建立)。這容許bean工廠優化其緩存less
6:獲取RootBeanDefinition,在XmlBeanFactory解析的時候會將bean註冊到beanDefinitionMap中,這裏就是在beanDefinitionMap中get,若是不存在則會拋出bean not found異常,同時會將GenericBeanDefinition轉換成RootBeanDefinition,由於存入時時GenericBeanDefinition;ide
7:檢查BeanDefinition是不是abstract,若是是則拋出,bean is Aastract異常;
8:檢查依賴,保證該bean因此依賴的bean都已經初始化,首先這裏要了解depends-on用來表示一個bean A的實例化依靠另外一個bean B的實例化, 可是A並不須要持有一個B的對象,若是須要的話就不用depends-on;不理解能夠看這篇文章
9:判斷bean的類型,是single仍是proptotype,對應的建立bean,或者沒有指定scope的判斷,其中出現最多的方法就是getObjectForBeanInstance,後續會一點點的解析它的源碼;
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//檢查緩存中是否存在實例 isSingletonCurrentlyInCreation 該實例是否在建立中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//若是緩存中實例爲null 則鎖定全局變量singletonObjects並進行處理
synchronized (this.singletonObjects) {
//嘗試從earlySingletonObjects (建立中提前曝光的beanFactory) 獲取bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//嘗試從singletonFactories獲取beanFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//返回獲取到的bean
singletonObject = singletonFactory.getObject();
//增長緩存
this.earlySingletonObjects.put(beanName, singletonObject);
//刪除緩存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}複製代碼
首先單例是隻容許建立一次,而且單例支持解決循環依賴,第一步會從singletonObjectsMap中獲取單例,若是發現不存在的話,再經過singletonsCurrentlyInCreation判斷下當前bean是否在建立,若是是則從提早曝光的Map earlySingletonObjects中獲取,若是依舊不能存在則在singletonFactories中獲取BeanFactory,經過getBean進行返回,反之結束了,緩存沒有,只能去從新建立了;
/**
* Return whether the specified prototype bean is currently in creation
* (within the current thread).
* @param beanName the name of the bean
*/
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}複製代碼
在這裏判斷了原型實例是否存在循環依賴,好比A中有B,B中有A,這種狀況只有單例模式纔會嘗試去建立,由於單例模式會提前包曝光實例,存在緩存中,原型模式是不容許的,會拋出類正在建立異常
if (!typeCheckOnly) {
// 將指定的bean標記爲已經建立(或即將建立)。這容許bean工廠優化其緩存
markBeanAsCreated(beanName);
}
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating // the bean... just in case some of its metadata changed in the meantime. clearMergedBeanDefinition(beanName); this.alreadyCreated.add(beanName); } } } }複製代碼
在上述源碼中咱們能夠看到,這段代碼的含義就是講指定的bean標記爲已經在建立或者即將建立;在clearMergedBeanDefinition方法中能夠看到,若是沒有標記bean正在建立則會刪除BeanDefinnition,接下來會從新建立;
/**
* Return a merged RootBeanDefinition, traversing the parent bean definition
* if the specified bean corresponds to a child bean definition.
* @param beanName the name of the bean to retrieve the merged definition for
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}複製代碼
在getBeanDefinition方法中,spring是直接從DefaultListAbleBeanFactory中的beanDefinitionMap獲取註冊時的BeanDefinition;
/**
* Return a RootBeanDefinition for the given bean, by merging with the
* parent if the given bean's definition is a child bean definition. * @param beanName the name of the bean definition * @param bd the original bean definition (Root/ChildBeanDefinition) * @param containingBd the containing bean definition in case of inner bean, * or {@code null} in case of a top-level bean * @return a (potentially merged) RootBeanDefinition for the given bean * @throws BeanDefinitionStoreException in case of an invalid bean definition */ protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException { synchronized (this.mergedBeanDefinitions) { RootBeanDefinition mbd = null; // Check with full lock now in order to enforce the same merged instance. if (containingBd == null) { mbd = this.mergedBeanDefinitions.get(beanName); } if (mbd == null) { if (bd.getParentName() == null) { // Use copy of given root bean definition. if (bd instanceof RootBeanDefinition) { mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } } else { // Child bean definition: needs to be merged with parent. BeanDefinition pbd; try { String parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); } else { BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without an AbstractBeanFactory parent"); } } } catch (NoSuchBeanDefinitionException ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); } // Deep copy with overridden values. mbd = new RootBeanDefinition(pbd); mbd.overrideFrom(bd); } // Set default singleton scope, if not configured before. if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON); } // A bean contained in a non-singleton bean cannot be a singleton itself. // Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status. if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { mbd.setScope(containingBd.getScope()); } // Cache the merged bean definition for the time being // (it might still get re-merged later on in order to pick up metadata changes) if (containingBd == null && isCacheBeanMetadata()) { this.mergedBeanDefinitions.put(beanName, mbd); } } return mbd; } }複製代碼
在getMergedBeanDefinition方法中作了幾件事情:
1:首先從緩存中mergedBeanDefinitions獲取BeanDefinition
2:經過有參構造方法初始化RootBeanDefinition,這裏的實例化涉及到一些參數的Set操做,具體代碼就不展現了,在AbstractBeanDefinition的有參構造方法中;
3:指定bean的scope;
4:把RootBeanDefinition加入緩存mergedBeanDefinitions中;
在這裏只是實例化就很少說了具體的DeBug一下就明白了,很簡單;
/**
* Check the given merged bean definition,
* potentially throwing validation exceptions.
* @param mbd the merged bean definition to check
* @param beanName the name of the bean
* @param args the arguments for bean creation, if any
* @throws BeanDefinitionStoreException in case of validation failure
*/
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}複製代碼
checkMergedBeanDefinition方法是判斷BeanDefinition是不是Abstract,若是是則拋出beanIsAbstractException,這裏就不過多解釋了,學過java的都懂;
// 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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}複製代碼
在這個方法中,若是當前Bean是有依賴的話就會先去GetBean他的依賴,保證當前bean的全部依賴都是初始化過可用的,getBean你們都不陌生吧,就是BeanFactory的getBean;
// Create bean instance.
// 建立bean實例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}複製代碼
上述代碼就是建立Bean的一個主方法,首先是調用了getSingleton,接着又用lambda執行了createBean方法,緊着這又調用了getObjectForBeanInstance方法;
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("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.
// 鎖定class根據class 屬性或者className 來解析class
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.
// 給BeanPostProcessors一個返回代理而不是目標bean實例的機會
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.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}複製代碼
上述代碼作了什麼:
1:解析class,若是BeanDefinition中存在beanClass,則直接返回,反之須要經過ClassLoader加載,代碼就不發了,可自行看源碼;
2:方法注入,就是lookup-method的注入注入方式,這裏就很少贅述了,可看上一遍文章;
3:spring的原文解釋是給BeanPostProcessors一個返回代理而不是目標bean實例的機會,這裏涉及Aop的代理,後續文章會詳細解釋;
4:調用doCreateBean進行建立,咱們直接看doCreateBean方法:
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
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) {
//使用對應的策略建立實例 好比工廠
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.
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;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 是否須要提早暴露, 單例&容許循環依賴&當前bean正在建立中 singletonsCurrentlyInCreation在DefaultSingletonBeanRegistry 225行建立,在建立bean以前記錄 正在建立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");
}
// 在bean未實例化以前加入到緩存中,單例支持循環依賴
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 對bean進行補充,屬性注入,bean依賴
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) {
Object earlySingletonReference = getSingleton(beanName, false);
//earlySingletonReference 再有在檢查循環依賴的時候纔不爲空
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 " +
"'getBeanNamesOfType' 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的流程可是真正的createBean還不是在這個方法,在createBeanInstance中,咱們先看看CreateBeann方法都作了什麼:
1:使用對應的策略建立實例 createBeanInstance方法;
2:判斷是否提早暴露,條件是( 單例&容許循環依賴&當前bean正在建立中 singletonsCurrentlyInCreation在DefaultSingletonBeanRegistry 225行建立,在建立bean以前記錄 正在建立bean),若是須要則調用addSingletonFactory方法在bean未實例化以前加入到緩存中,單例支持循環依賴;
3:對bean進行補充,屬性注入,bean依賴;對ByName,ByType依賴進行初始化並註冊依賴Bean;
4:調用初始化方法;
5:對依賴處理;
/**
* 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
* @see #obtainFromSupplier
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//確保class不爲空,而且訪問權限爲public
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());
}
//配置的一種特殊的callback回調方法,經過這個callback建立bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 若是工廠方式不爲空,則使用功能工廠方式進行解析
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 一個類可能有多個構造器,因此Spring得根據參數個數、類型肯定須要調用的構造器
// 在使用構造器建立實例後,Spring會將解析事後肯定下來的構造器或工廠方法保存在緩存中,避免再次建立相同bean時再次解析
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//判斷構造器或工廠方法是否爲null
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
//已經解析過class的構造器
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
//構造函數自動注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
//使用默認構造器
return instantiateBean(beanName, mbd);
}
}
// 須要根據參數解析、肯定構造函數
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
// 默認構造的首選構造器?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 使用默認構造器
return instantiateBean(beanName, mbd);
}複製代碼
上述方法:
1:解析class;
2:若是存在 Supplier 回調,則調用 obtainFromSupplier() 進行初始化,若是不等於null就直接返回;
3:若是工廠方式不爲空,則使用功能工廠方式進行解析;
4:構造函數自動注入 autowireConstructor
5:默認構造器 instantiateBean
//配置的一種特殊的callback回調方法,經過這個callback建立bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}複製代碼
/**
* Obtain a bean instance from the given supplier.
* @param instanceSupplier the configured supplier
* @param beanName the corresponding bean name
* @return a BeanWrapper for the new instance
* @since 5.0
* @see #getObjectForBeanInstance
*/
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}複製代碼
/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
複製代碼
Supplier就一個get方法,該方法會返回一個 T 類型的對象,有點兒相似工廠方法。這個接口有什麼做用?用於指定建立 bean 的回調,若是咱們設置了這樣的回調,那麼其餘的構造器或者工廠方法都會沒有用。在什麼設置該參數呢?Spring 提供了相應的
setter
方法,以下:
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}複製代碼
該方法是AbsTractBeanDefinition類中的方法,在初始化RootBeanDefinition的時候會調用該方法;在源碼的protected AbstractBeanDefinition(BeanDefinition original) 方法中;
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
// 實例化 BeanWrapperImpl
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化 BeanWrapperImpl
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
// 獲取工廠Bean 這裏使用FactoryBean 縣實例化 FactoryBean
// 工廠名稱不爲空 以下處理
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");
}
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// 工廠名爲空,則其多是一個靜態工廠
// It's a static factory method on the bean class. // 這裏使用Factory-method factory-metohd 無需調用功能工廠類實例下就能夠調用工廠功法 但非static不能夠 須要調用上邊的 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; ArgumentsHolder argsHolderToUse = null; //要使用的工廠參數 Object[] argsToUse = null; // 工廠方法的參數 // 若是指定了構造參數則直接使用 // 在調用 getBean 方法的時候指定了方法參數 if (explicitArgs != null) { argsToUse = explicitArgs; } else { // 沒有指定,則嘗試從配置文件中解析 Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { // 獲取構造函數或工廠方法 factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod; if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) { // 獲取構造參數 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 獲取構造函數參數的包可見字段 argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { // 緩存中存在,則解析存儲在 BeanDefinition 中的參數 // 如給定方法的構造函數 A(int ,int ),則經過此方法後就會把配置文件中的("1","1")轉換爲 (1,1) // 緩存中的值多是原始值也有多是最終值 argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true); } } if (factoryMethodToUse == null || argsToUse == null) { // Need to determine the factory method... // Try all methods with this name to see if they match the given arguments. // 須要肯定工廠的方法.嘗試全部具備此名稱的方法,以查看它們是否與給定的參數匹配。 // 獲取工廠方法的類全名稱 factoryClass = ClassUtils.getUserClass(factoryClass); // 檢索全部方法,這裏是對方法進行過濾 Method[] rawCandidates = getCandidateMethods(factoryClass, mbd); List<Method> candidateList = new ArrayList<>(); for (Method candidate : rawCandidates) { // 若是有static 且爲工廠方法,則添加到 candidateSet 中 if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) { candidateList.add(candidate); } } // 若是靜態方法就一個 & getBean參數null & 沒有構造參數值 直接初始化返回 if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) { Method uniqueCandidate = candidateList.get(0); if (uniqueCandidate.getParameterCount() == 0) { mbd.factoryMethodToIntrospect = uniqueCandidate; synchronized (mbd.constructorArgumentLock) { mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate; mbd.constructorArgumentsResolved = true; mbd.resolvedConstructorArguments = EMPTY_ARGS; } bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS)); return bw; } } Method[] candidates = candidateList.toArray(new Method[0]); // 排序構造函數 // public 構造函數優先參數數量降序,非public 構造函數參數數量降序 AutowireUtils.sortFactoryMethods(candidates); ConstructorArgumentValues resolvedValues = null; boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Method> ambiguousFactoryMethods = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
// 判斷 BeanDefinition中有沒有構造參數值
// getBean() 沒有傳遞參數,則須要解析保存在 BeanDefinition 構造函數中指定的參數
if (mbd.hasConstructorArgumentValues()) {
// 獲取構造參數值
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析構造函數的參數
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
LinkedList<UnsatisfiedDependencyException> causes = null;
// 循環方法找到 匹配的那個
for (Method candidate : candidates) {
// 獲取方法參數
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
// getbean給的參數
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 對象
// ParameterNameDiscoverer 是用於解析方法和構造函數的參數名稱的接口,爲參數名稱探測器
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;
}
}
// isLenientConstructorResolution 判斷解析構造函數的時候是否以寬鬆模式仍是嚴格模式
// 嚴格模式:解析構造函數時,必須全部的都須要匹配,不然拋出異常
// 寬鬆模式:使用具備"最接近的模式"進行匹配
// typeDiffWeight:類型差別權重
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);
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) {
// 指定工廠方法
mbd.factoryMethodToIntrospect = factoryMethodToUse;
// 將解析的構造函數加入緩存
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
Assert.state(argsToUse != null, "Unresolved factory method arguments");
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}複製代碼
上述這段代碼,怎麼說呢,爲何都寫一塊兒,爲何不分方法寫,每一個方法明確幹什麼,看這個方法須要毅力,讀者好好看....... 先來看看這個方法都作了啥:
1:首先實例化 BeanWrapperImpl
2:初始化BeanWrapperImpl
3:獲取FactoryBean Name,看這裏以前讀者若是不瞭解factory-bean和factory-mothod請點擊,在這裏會判斷factoryBeannName是否爲null,若是不是則初始化工廠bean,代碼體如今factoryBean = this.beanFactory.getBean(factoryBeanName)這裏,不然必定是一個static修飾的工廠方法,直接調用便可;
4:緩存中獲取構造或工廠方法,構造參數,在線解釋一下:;
- constructorArgumentLock:構造緩存使用的鎖;
- resolvedConstructorOrFactoryMethod:構造函數或工廠方法;
- resolvedConstructorArguments:構造參數
若是緩存中存在,則須要調用
resolvePreparedArguments()
方法進行轉換,由於緩存中的值有多是最終值也有可能不是最終值,好比咱們構造函數中的類型爲 Integer 類型的 1 ,可是原始的參數類型有多是 String 類型的 1 ,因此即使是從緩存中獲得了構造參數也須要通過一番的類型轉換確保參數類型徹底對應。5:若是緩存中或上送的參數沒有則須要解析了,須要經過反射獲取全部方法,若是獲取的符合條件的static的方法就一個,而且尚未構造方法參數,則直接初始化返回;代碼以下:
// 若是靜態方法就一個 & getBean參數null & 沒有構造參數值 直接初始化返回
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidateList.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}複製代碼
6:若是顯示提供了參數(explicitArgs != null),則直接使用,反之須要獲取ConstructorArgumentValues值,而且解析構造函數,這裏比較複雜,建議讀者debug;
7:循環匹配,直到找到匹配的構造函數;若是找不到則拋出異常,無可用函數;代碼以下:
// 循環方法找到 匹配的那個
for (Method candidate : candidates) {
// 獲取方法參數
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
// getbean給的參數
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 對象
// ParameterNameDiscoverer 是用於解析方法和構造函數的參數名稱的接口,爲參數名稱探測器
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;
}
}
// isLenientConstructorResolution 判斷解析構造函數的時候是否以寬鬆模式仍是嚴格模式
// 嚴格模式:解析構造函數時,必須全部的都須要匹配,不然拋出異常
// 寬鬆模式:使用具備"最接近的模式"進行匹配
// typeDiffWeight:類型差別權重
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);
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") + ".");
}複製代碼
8:指定工廠那個方法,而且將解析的構造函數信息加入緩存中,代碼以下:
if (explicitArgs == null && argsHolderToUse != null) {
// 指定工廠方法
mbd.factoryMethodToIntrospect = factoryMethodToUse;
// 將解析的構造函數加入緩存
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
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;
}
}
}複製代碼
10:經過反射實例化Bean,源碼:
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, 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);
// 利用反射
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 (IllegalArgumentException ex) {
throw new BeanInstantiationException(factoryMethod,
"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(factoryMethod,
"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
}
catch (InvocationTargetException ex) {
String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
"declaring the factory method as static for independence from its containing instance. " + msg;
}
throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
}
}複製代碼
工廠實例化和構造函數實例化這兩個大方法都須要讀者本身deBug,這樣可更好的理解下面說一下都作了什麼:
1:實例化BeanWrapperImpl
2:初始化BeanWrapperImpl
3:構造參數若是在getBean是傳入則使用,反之須要從緩存中獲取並解析參數類型:
- constructorArgumentLock:構造緩存使用的鎖;
- resolvedConstructorOrFactoryMethod:構造函數或工廠方法;
- resolvedConstructorArguments:構造參數
代碼以下:
Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { //獲取解析構造函數或工廠方法 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; //構造函數或工廠方法不爲空 & 存在構造方法(函數) if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor... argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 配置構造函數參數 argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { // 解析參數類型,好比構造方法是 A(int, int),經過此方法將("1","1")轉換爲(1,1) argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); }複製代碼
4:解析構造函數,若是中有上送,則使用,若是沒有則從beanClass中獲取,解析後加入緩存,代碼是:
if (constructorToUse == null || argsToUse == null) { // 接受指定的構造函數(若是有的話)。. Constructor<?>[] candidates = chosenCtors; if (candidates == null) { // 從class中獲取 Class<?> beanClass = mbd.getBeanClass(); try { // 從class獲取構造器 判斷是不是public 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); } } // 構造參數value == null 直接返回 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; } bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS)); return bw; } } // 須要解析構造函數參數 boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); // 解析構造函數參數 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; for (Constructor<?> candidate : candidates) { //獲取構造方法參數類型 Class<?>[] paramTypes = candidate.getParameterTypes(); 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; } if (paramTypes.length < minNrOfArgs) { //參數個數不相等 continue; } ConstructorResolver.ArgumentsHolder argsHolder; if (resolvedValues != null) { try { // 從註解上獲取參數名稱 String[] paramNames = ConstructorResolver.ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); if (paramNames == null) { // 參數名稱探索期 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { //獲取構造方法上的參數 paramNames = pnd.getParameterNames(candidate); } } argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1); } 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; } } else { // 無參構造 // Explicit arguments given -> arguments length must match exactly. if (paramTypes.length != explicitArgs.length) { continue; } argsHolder = new ConstructorResolver.ArgumentsHolder(explicitArgs); } // 判斷是否有不肯定的構造 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // Choose this constructor if it represents the closest match. if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } 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); } if (explicitArgs == null && argsHolderToUse != null) { // 加入緩存 argsHolderToUse.storeCache(mbd, constructorToUse); } }複製代碼
5:實例化Bean,源碼:
@Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, final Constructor<?> ctor, Object... args) { // 若是沒使用lookuo 或 replace 則直接使用反射建立 if (!bd.hasMethodOverrides()) { if (System.getSecurityManager() != null) { // use own privileged to change accessibility (when security is on) AccessController.doPrivileged((PrivilegedAction<Object>) () -> { ReflectionUtils.makeAccessible(ctor); return null; }); } // 直接使用反射方式建立你 return BeanUtils.instantiateClass(ctor, args); } else { return instantiateWithMethodInjection(bd, beanName, owner, ctor, args); } }複製代碼
/**
* 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
*/
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
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);
}
}
複製代碼
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides. if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { //獲取構造器 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { // 獲取clazz 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( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { // 獲取公共構造器 constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } // 實例化class return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); } }複製代碼
上述代碼是使用默認構造器實例化Bean的代碼,這裏我就很少贅述了,使用工廠模式和構造參數實例化Bean的代碼都看過了,這裏就很容易理解了;下面咱們接着流程說getSingleton方法:
/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 加鎖,全局變量須要同步
synchronized (this.singletonObjects) {
//查看單例bean是否建立國若是有直接使用
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//記錄加載狀態 書中 99頁
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//刪除加載狀態
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}複製代碼
這裏咱們直接說這個方法幹了什麼事情吧,以下:
1:首先是全局鎖singletonObjects;
2:查看緩存中是否存在,若是有則判斷獲取的Bean是否在銷燬階段;
3:使用singletonsCurrentlyInCreation記錄加載狀態;
4:使用createBean方法返回的ObjectFactory獲取bean,並指定此次建立是一個新的單例;
5:在singletonsCurrentlyInCreation中刪除加載狀態;
6:增長緩存,代碼以下:
/** * Add the given singleton object to the singleton cache of this factory. * <p>To be called for eager registration of singletons. * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }複製代碼
/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a FactoryBean.
* @param beanInstance the shared bean instance
* @param name name that may include factory dereference prefix
* @param beanName the canonical bean name
* @param mbd the merged bean definition
* @return the object to expose for the bean
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 若是指定的name是工廠相關的(&前綴),而且beanInstance又不是FactoryBean類 則驗證不經過
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. //若是咱們有了個bean的實例,這個實例多是bean多是beanfactory,若是是FactoryBean咱們使用它去建立實例,可是若是用戶想要直接獲取工廠實例而不是工廠的getObject方法所對應的實例, //那麼傳入的name應該加前綴& if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { //嘗試從緩存中加載實例 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. // beanInstance必定是FactoryBean了 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. //在beanDefinitionMap 獲取beanDefition ,beanDefinitionMap是註冊時候的Map if (mbd == null && containsBeanDefinition(beanName)) { // 將xml解析時存入的GernericBeanDefinition 轉換成 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); } //是不是用戶定義而不是應用程序自己定義 boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }複製代碼
上述代碼有兩個判斷:
1:若是指定的name是工廠相關的(&前綴),而且beanInstance類型不是FactoryBean則拋出BeanIsNotAFactoryBean異常;
2:若是beanInstance不是FactoryBean 或者 指定的name是工廠相關的(&前綴)則直接返回beanInstance;
這兩個條件能夠好好理解下,第一個應該沒問題,若是指定的是工廠相關的,而且beanInstance類是否是FactoryBean則拋出異常,第二個就能夠理解beanInstance若是不是FactoryBean就直接返回, 而且第二個條件的BeanFactoryUtils.isFactoryDereference(name)永遠都不會是true,由於若是這一條件成立,則第一個條件則通不過會直接拋出異常,那麼下邊的代碼就是在處理beanInstrace是BeanFactory,可是傳入的name不是&name;
3:下面的代碼就很簡單了,mbd這個參數不會爲null,只有在獲取緩存的時候會是null,這裏就不作多解釋了,直接將BeanInstance類型強轉成FactoryBean<T>,而後調用getObjectFromFactoryBean方法進行getObject返回;
4:FactoryBean不理解的能夠看一下這篇文章,有例子:blog.csdn.net/qq_30257149…
總結一下,在getSinngnleton中不斷的使用緩存就是由於是單例的不容許重複建立,說一下重點:
1:若是是單例則先從緩存中獲取,沒有在調用getSingleton方法建立;
2:檢查bean是不是abstract
3:保證當前bean所依賴的bean的初始化,若是沒有先初始化依賴;
4:獲取BeanDefinition,BeanDefinition是在註冊的時候實例化而後存入緩存的,這裏直接取過來作一下類型轉換便可;
5:若是是單例則調用getSingleton方法,若是是原型則調用isPrototype下面的代碼塊,若是都不是的話使用默認建立(原型);
6:在bean建立先後會使用singletonsCurrentlyInCreation或prototypesCurrentlyInCreation標記類是否正在建立中,給後續判斷使用;
7:bean實例化的方式,在建立實例以前作了一個判斷,若是有則經過InstanceSupplier.et方法直接返回,工廠方法實例化(instantiateUsingFactoryMethod),構造器實例化(autowireConstructor),默認構造器實例化(instantiateBean),這裏是讀者須要看源碼的的重點,
8:bean在建立前會提早暴露實例並增長緩存,保證若是有別人依賴能夠直接從緩存你中取,解決循環依賴問題;
9:對bean的賦值屬性的注入(populateBean方法);
10:調用初始化方法,initializeBean;
對於9和10在代碼中沒有作詳細的講解,可是在源碼中作了一些註釋,能夠自行debug看一下很簡單,主要是太多了,早知道就分開寫了,很累.... 不知道做爲讀者的你可否能看下去;
碼字不易,轉你發請註明出處:mp.csdn.net/postedit/88… 或 juejin.im/editor/draf…