Srping源碼之BeanFactory.getBean
本文是針對Srping的BeanFactory.getBean來進行源碼解析,如果您是第一次看請先看一下XMLBeanFactory解析://www.cnblogs.com/technology-blog/p/14543685.html,可以更好的理解Spring的註冊原理,本篇博客是跟源碼一步步看spring怎麼實現getBean源碼,Spring版本為5.X,源碼已經在每一行上加了注釋,方便讀者學習。
- 廢話不多說,我們直接看源碼:
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()
/**
* 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的源碼比較長,那它都做了哪些事情呢:
1:轉換對應的beanname,可能有很多人不理解,傳入進來的不就應該是beanName嘛,其實傳入的可能是BeanFactory,也可能是別名,如果是BeanFactory,就要去除它的修飾符,比如傳入進來的&aa,就要轉換成aa,但如果傳入進來的是別名,就要取alias對應的最終的beanName,例如別名A指向了B的bean則返回B的beanName,如果別名A指向了別名B,別名B指向了C,則要返回C的BeanName;
2:檢查單例中是否存在實例,會先從緩存中獲取,下面會詳細講解;
3:判斷原型實例是否存在循環依賴,比如A中有B,B中有A,這種情況只有單例模式才會嘗試去創建,因為單例模式會提早包曝光實例,存在緩存中,原型模式是不允許的,會拋出類正在創建異常;
4:通過父BeanFactory獲取bean;
5:將指定的bean標記為已經創建(或即將創建)。這允許bean工廠優化其緩存
6:獲取RootBeanDefinition,在XmlBeanFactory解析的時候會將bean註冊到beanDefinitionMap中,這裡就是在beanDefinitionMap中get,如果不存在則會拋出bean not found異常,同時會將GenericBeanDefinition轉換成RootBeanDefinition,因為存入時是GenericBeanDefinition類型;
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進行返回,反之結束了,緩存沒有,只能去重新創建了;
- 接下來看isPrototypeCurrentlyInCreation
/**
* 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,這種情況只有單例模式才會嘗試去創建,因為單例模式會提早包曝光實例,存在緩存中,原型模式是不允許的,會拋出類正在創建異常
- markBeanAsCreated方法源碼:
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,接下來會重新創建;
- 繼續看getMergedLocalBeanDefinition源碼:
/**
* 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一下就明白了,很簡單;
- 我們繼續看checkMergedBeanDefinition方法:
/**
* 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的都懂;
- 接下來就要看當前Bean的依賴,需要先實例化依賴:
// 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;
- 下面我們看bean的創建流程singleton:
// 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方法;
- 先來看createBean再看getSingleton方法:
/**
* 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方法:
- 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:對依賴處理;
- 看一下createBeanInstance方法:
/**
* 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
- 我們先看看 Supplier回調的使用:
//配置的一種特殊的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) 方法中;
- 下面開始解析工廠模式實例化Bean,後邊還有構造函數和默認構造的實例方法…..累
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());
}
}
- 上述工廠模式實例化Bean寫的不是很詳細,盡量debug源碼去一步步看才能理解,下面看構造器實例化autowireConstructor
工廠實例化和構造函數實例化這兩個大方法都需要讀者自己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); } }
- 下面說一下默認構造器instantiateBean實例化Bean:
/**
* 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方法:
- 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); } }
- 接下來就看一看getBean調用最多的方法getObjectForBeanInstance:
/**
* 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
,然後調用getObjectFromFactoryBean方法進行getObject返回; 4:FactoryBean不理解的可以看一下這篇文章,有例子://blog.csdn.net/qq_30257149/article/details/88028924
總結
總結一下,在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看一下很簡單,主要是太多了,早知道就分開寫了,很累…. 不知道作為讀者的你能否能看下去;