spring源码之:循环依赖

AbstractBeanFactory的作用:别名管理,单例创建与注册,工厂方法FactoryBean支持.

由图我们直接的看出,AbstractBeanFactory继承了FatoryBeanRegistrySupport的同时,也实现了ConfigurableBeanFactory,可想而知abstractFactoryBean的功能有多强大,这里只是简单的猜测,我们来看它的具体实例.

一. AbstractBeanFactory的作用

  • api里是这样说的,是抽象BeanFactory的基类,同时实现了ConfigurableBeanFactory的SPI,提供了所有的功能
  • 也可以从我们定义的资源中resource中来获取bean的定义.
  • 也提供了单例bean的缓存通过DefaultSingletonBeanRegistry,同时提供了单例和多例和别名的定义等操作.
  • 上述只是其中的一部分,总之来说它的作用还是挺大的.

二.源码阅读

由于该类方法较多,这里我们简单的说几个重要的方法,首先是实现了BeanFactory接口的getBean()方法:

//获取bean
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

该方法是实现了BeanFactory接口的getBean()方法,spring里面都是一般这样做的,获取某个东西,实际上封装了一层内部调用如上述代码的doGetBean()方法,那么该方法肯定是我们学习的重要目标了,那么它到底是做了什么我们来看,代码如下:

package org.springframework.beans.factory.support;

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
} protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
throws BeansException { //提取对应的beanName
final String beanName = transformedBeanName(name);
Object bean; //检查缓存中或者实例工厂中是否有对应的实例
//为什么首先会出现这段代码呢,因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
//Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光,也就是将ObjectFactory加入到缓存中,
//一旦下个bean创建时候需要依赖上个bean则直接使用
//尝试从缓存获取或从singletonFactories中的ObjectFactory中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
//只有在单例情况下才会尝试解决依赖循环,原型模式情况下,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候
//就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是isPrototypeCurrentlyInCreation(beanName)
//为true
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
} //如果不是仅仅做类型检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} try {
//将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,
//如果指定BeanName是子Bean的话同时会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args); // 若存在依赖则需要递归实例化依赖的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后便可以实例化mbd本身了
//singleton模式的创建
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);
}
//prototype模式的创建
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
//指定的scope上实例化bean
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;
}
} //检查需要的类型是否符合bean的实际类型
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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
}

Bean的加载经历了一个相当复杂的过程,总结下bean加载过程的大致步骤如下:

(1)转换对应的beanName

或许很多人不理解转换对应beanName是什么意思,传入的参数name不就是beanName吗?其实不一定,这里传入的name有可能是别名,也可能是FactoryBean,所以需要进行一系列的解析,这些解析内容包括如下内容:

i.去除FactoryBean的修饰符,也就是如果name="&aa",那么会首先去除&,而是name="aa"。

ii.取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B,若别名A指向别名B,别名B又指向名称为C的bean则返回C

(2)尝试从缓存中加载单例

单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直使用ObjectFactory。

(3)bean的实例化

如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里有必要强调一下,缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,加入我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法返回的bean,而getObjectForBeanInstance就是完成这个工作的。

(4)原型模式的依赖检查

只有在单例情况下才会尝试解决循环依赖--《spring源码之:循环依赖》,如果存在A中有B属性,B中有A属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况:isPrototypeCurrentInCreation(beanName)==true。

(5)检测parentBeanFactory

从代码上看,如果缓存没有数据的话直接转到父类工厂上去加载了,这是为什么呢?

可能我们忽略了一个很重要的判断条件:parentBeanFactory != null && !containsBeanDefinition(beanName),parentBean如果为空,则一切免谈,这个显而易见。但是containBeanDefinition(beanName)就比较重要了,它是检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下了,然后再去递归的调用getBean方法。

(6)将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition。

因为从XML配置文件中读取到的Bean信息是存储在GenericBeanDefinition中的,但是所有的Bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性。

(7)寻找依赖

因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以在Spring的加载顺序中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。

(8)针对不同的scope进行bean的创建

我们都知道,在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他的配置诸如prototype、request、session之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略。

(9)类型转换

程序到这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是为空的,但是可能会存在这样的情况,返回的bean其实是个String,但是requiredType却传入Integer类型,那么这个时候本步骤就会起作用了,他的功能是将返回的bean转换为requiredType所指定的类型。

经过上面的步骤后bean的加载就结束了,这个时候就可以返回我们所需要的bean了,在细化分析各个步骤提供的功能前我们有必要先了解下FactoryBean的用法。

上面代码是spring如何获取bean的过程,实际最核心的是createBean() 方法,该方法真正的创建bean的过程

/**
* 该方法是AbstractAutowireCapableBeanFactory中的实现方法
*
*/
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.
//解析bean的class
//1.这里当解析的resolvedClass和mbd.hasBeanClass()为falsembd.getBeanClassName()同时成立时
//2.这里需要我们new一个合并的beanDefinition类,同时设置class类型
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} //覆盖了RootBeanDefinition的prepareMethodOverrides方法
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
} try {
//获取一个解析之后的代理bean的实例,而不是真正的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 {
//这里才是真正的执行创建bean的方法
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);
}
}

再来看真正的创建bean的方法:

/**
* 该方法是真正的创建bean的方法
* @param beanName 要创建bean的名称
* @param mbd 定义bean的beanDefinition文件
* @param args 创建bean时,构造方法所需的参数或者是调用bean工厂时来创建bean所需的参数
* @return 完成创建之后的bean的实例
* @throws BeanCreationException
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException { //实例化bean的过程
BeanWrapper instanceWrapper = null;
//如果是单例,从factoryBeanInstanceCache中移除相应的bean实例
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//创建实例
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//获取封装实例
final Object bean = instanceWrapper.getWrappedInstance();
//获取对应实例的class类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
//将获取到的bean类型赋值给mbd的resolvedTargetType
//resolvedTargetType用来保存真实类型bean的类型
mbd.resolvedTargetType = beanType;
} // Allow post-processors to modify the merged bean definition.
//允许后置处理修改mbd
synchronized (mbd.postProcessingLock) {
//postProcessed默认为false,故不能修改,这里取反表示可以修改
if (!mbd.postProcessed) {
try {
//对bean进行后置处理
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
} //处理循环引用和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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} //初始化bean实例
Object exposedObject = bean;
try {
//给bean的实例填充属性
populateBean(beanName, mbd, instanceWrapper);
//初始化bean的实例
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);
}
}
//引用问题处理,这里先暴露早期单例引用的bean
if (earlySingletonExposure) {
//从缓存注册中获取,这里不允许早期引用的创建
Object earlySingletonReference = getSingleton(beanName, false);
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.");
}
}
}
} //注册bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
} return exposedObject;
}

上述就是spring创建bean的过程,实际上真正创建bean的方法在doCreateBean这里,关于spring的如何获取bean的过程在后续再说.

1、缓存中获取单例bean

  介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了。前面已经提到过,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。

package org.springframework.beans.factory.support;

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
} protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否存在实例,1从singletonObjects获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//如果为空且正在创建则锁定全局变量进行处理
synchronized (this.singletonObjects) {
//2.从earlySingletonObjects获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//如果为空且allowEarlyReference为true则获取singletonFactories中的实例,3从singletonFactories获取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
//记录在缓存earlySingletonObjects中
this.earlySingletonObjects.put(beanName, singletonObject);
//在缓存singletonFactories中删除该实例
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
}

这个方法因为涉及循环依赖的检测,以及涉及很多变量的记录存取,所以让人摸不着头脑。这个方法首先尝试从singletonObjects里面获取实例,如果获取不到再从earlySingletonObjects里面获取,如果还获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject来创建bean,并放到earlyReferenceObjects里面去,并且从singletonFactories里面remove掉ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是allowEarlyReference为true的情况下使用。

这里涉及用于存储bean的不同的map,可能会让我们感到崩溃,简单的解析一下:

  • singletonObjects:用于保存BeanName和创建bean实例之间的关系,bean name --> bean instance
  • singletonFactories:用于保存BeanName和创建bean的工厂之间的关系,bean name --> ObjectFactory。与earlySingletonObjects互斥
  • earlySingletonObjects:也是保存BeanName和创建bean实例之间的关系,与singletonObjects不同的地方在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中就可以通过getBean获得了,其目的是用来检测循环引用。与singletonFactories互斥
  • registeredSingletons:用来保存当前所有已注册的bean

2、从bean的实例获取对象

在getBean方法中,getObjefctForBeanInstance是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。总之,我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject方法作为返回值

无论是从缓存中获取到的bean还是通过不同的scope策略加载的bean都只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,假如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法返回的bean,而getObjectForBeanInstance方法就是干这个工作的。

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { //如果指定的name是工厂相关(以&为前缀)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
//如果beanInstance不是FactoryBean类型,则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
} //现在我们有了一个bean实例,这个实例可能是FactoryBean也可能是正常的bean,
//如果是FactoryBean我们使用创建实例,但是如果用户想要直接获取工厂实例而不是工厂getObject所对应的实例
//那么传入的name应该加前缀&
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
} //剩下的就是FactoryBean且是需要返回FactoryBean的getObject方法所对应的实例
Object object = null;
if (mbd == null) {
//尝试从缓存中加载bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//containsBeanDefinition检测beanDefinitionMap中也就是所有已经加载的类中检测是否定义benaName
if (mbd == null && containsBeanDefinition(beanName)) {
//将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefintion,如果指定BeanName是子Bean的话同时合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
//是否是用户定义的而不是应用程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

从上面的代码来看,其实这个方法并没有什么重要的信息,大多是些辅助代码以及一些功能性的判断,而真正核心的代码却委托给了getObjectFromFactoryBean,我们来看看getObjectForBeanInstance所做的工作

(1)对FactoryBean正确性的验证

(2)对非FactoryBean不做任何处理

(3)对bean进行转换

(4)将从Factory中解析bean的工作委托给getObjecFromFactoryBean

我们下面来看看getObjectFromFactoryBean方法的内容

package org.springframework.beans.factory.support;

public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//如果是单例模式
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//尝试从缓存中获取BeanName对应的实例
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
//判断是否在获取object期间已经在缓存中存储了BeanName对应的实例
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
//将BeanName和对应的实例加入缓存
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//其他模式则直接创建即可
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
}

很遗憾,在这个代码中我们还是没有看到想要看到的代码,在这个方法里只做了两件事,一件是保证单例模式的实例是唯一的,另一件就是对bean进行后处理。下面我们看一下后处理代码

package org.springframework.beans.factory.support;

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory { protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
} public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
}

对于后处理器的使用我们还未过多接触,后续文章会使用大量篇幅介绍,这里,我们只需要了解在Spring获取bean的规则中有这样一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际的开发中大可以针对此特性设计自己的业务逻辑。

在doGetObjectFromFactoryBean方法中我们终于看到了我们想要看到的方法,也就是factory.getObject(),我们下面来看一下

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException { Object object;
try {
//权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//直接调用getObject方法创建实例
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}

上面的代码没有什么难懂的地方,这里就不再赘述了。

3、获取单例

之前讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean就需要从头开始bean的加载过程了。而spring中使用getSingleton的重载方法实现bean的加载过程。下面我们来看一看代码:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
//全局变量需要同步
synchronized (this.singletonObjects) {
// 先检查bean是否已经加载过,因为singleton模式其实就是复用已创建的bean(1)
Object singletonObject = this.singletonObjects.get(beanName);
// 如果空才进行singleton的bean的初始化(2)
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the 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 + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
// 初始化bean
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 != NULL_OBJECT ? singletonObject : null);
}
}

上述代码其实是使用了回调方法,使得程序可以在单例中创建的前后做一些准备级处理操作,而真正获取单例bean的方法其实并不是在此方法中实现的,其实现逻辑是在ObjectFactory类型的实例singletonFactory的getObject方法中实现的。而这些准备及处理操作包括如下内容。

(1)检查缓存是否已经加载过

(2)若没有加载,则记录beanName的正在加载状态

(3)加载单例前记录加载装态

  可能你会觉得beforeSingletonCreation方法是个空实现,里面没有任何逻辑,但其实不是,这个函数中做了一个很重要的操作:记录加载状态,也就是通过this.singletonCurrentlyInCreation.add(beanName)将正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测,下面是代码:

protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

(4)通过调用参数传入的ObjectFactory的个体Object方法实例化bean

(5)加载单例后的处理方法调用。同步骤(3)记录加载状态相似,当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录。下面是代码:

protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

(6)将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态。下面是代码:

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);
}
}

(7)返回结果处理。

虽然我们已经从外部了解了加载bean的逻辑结构,但现在我们还并没有开始对bean加载功能的探索,之前提到过,bean的加载逻辑其实是在传入的ObjectFactory类型的singletonFactory中定义的,我们反推参数的获取,得到如下代码

sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});

ObjectFactory的核心部分其实只是调用了createBean的方法,所以我们还需要到createBean方法中追寻真理。

4、准备创建Bean

  我们不可能指望在一个函数中完成一个复杂的逻辑,而且我们跟踪了这么多的Spring代码,经历了这么多的函数,或多或少也发现了一些规律:一个真正干活的函数其实都是以do开头的,比如doGetObjectFromFactoryBean;而给我们错觉的函数,比如getObjectFromFactoryBean其实只是从全局角度去做些统筹的工作。这个规则对于createBean也不例外,那么让我们看看在createBean函数中都做了哪些准备工作。

createBean()在其抽象子类AbstractAutowireCapableBeanFactory.java中实现,代码如下:

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException { if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd; //锁定class,根据设置的class属性或者className解析class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} //验证及准备覆盖的方法,4.1
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
} try {
//给BeanPostProcessors一个机会来返回代理来代替真正的实例,4.2
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 {
//创建bean实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("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属性或者根据className来解析Class

(2)对override属性进行标记和验证。我们知道在Spring中是没有override-method这样的配置的,但是Spring配置中是存在lookup-method和replace-method的,而这两个配置的加载其实就是将配置统一存放在BeanDefinition中的methodOverrides属性里,而这个函数的操作 就是针对于这两个配置的。

(3)应用初始化前的后处理器,解析bean是否存在初始化前的短路操作

(4)创建bean

4.1、处理override属性

我们首先看下AbstractBeanDefinition.java中定义的prepareMethodOverride()方法,对override属性标记及验证的逻辑实现的代码:

    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
//判断是否overrideMethods中是否存在需要覆盖的方法
if (hasMethodOverrides()) {
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
//同步全局变量
synchronized (overrides) {
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
}
} //真正实现覆盖方法的方法
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
//获取对应类中对应方法名的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
//标记MethodOverrides暂未被覆盖,避免参数类型检查的开销
mo.setOverloaded(false);
}
}

通过上面两个函数的代码我们可以很清楚的看到Spring对于lookup-method和replace-method这两个配置的处理过程。前面我们知道,这两个配置属性是统一存放在了BeanDefinition的methodOverrides属性里,这两个功能的实现原理其实就是在bean实例化的时候如果检测到存在methodOverrides属性,会动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理,相关逻辑实现在bean的实例化部分详细介绍。

但是,这里要提到的一点是,对于方法的匹配来讲,如果一个类中存在若干个重载方法,那么,在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数。但是,Spring将一部分匹配工作在这里完成了,如果当前类中的方法只有一个,那么就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以对方法的存在性进行验证,正可谓一箭双雕。

4.2、实例化的前置处理

  在处理完overrideMethods属性后,我们可以看到Spring的代码中使用了这样的一个方法resolveBeforeInstantiation(beanName, mbd)对BeanDefinition中的属性做些前置处理。当然,无论其中是否有相应的逻辑实现我们都可以理解,因为真正逻辑实现前后留有处理函数也是可扩展的一种体现,但是,这并不是最重要的,在函数中还提供了一个短路判断,这才是最为关键的部分。

    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}

当经过前置处理后返回的结果如果不为空,那么会直接略过后续的Bean的创建而直接返回结果。这一特性虽然很容易被忽略,但是却起着至关重要的作用,我们熟知的AOP功能就是基于这里判断的。下面我们来看一下前置处理方法的代码:

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

此方法中最吸引我们的无疑是两个方法:applyBeanPostProcessorsBeforeInstantiation以及applyBeanPostProcessorsAfterInstantiation。两个方法实现的非常简单,无非是对后处理器中的所有InstantiationAwareBeanPostProcess类型的后处理器进行postProcessBeforeInstantiation方法和BeanPostProcess的postProcessAfterInitialization方法的调用

(一)实例化前后处理器的调用

bean的实例化前调用,也就是将AbstractBeanDefinition转化为BeanWrapper前的处理。给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean可能已经不是我们认为的bena了,而是或许成为一个经过处理的代理bean,可能是通过cglib生成的,也可能是通过其他技术生成的。这个在后面会详细介绍,我们只需要知道,在bean的实例化前会调用后处理器的方法进行处理。下面是代码:

    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}

(二)实例化后的后处理应用

在讲解从缓存中获取单例bean的时候就提到过,Spring中的规则是在bean的初始化后尽可能保证将注册的后处理器的postProcessAfterInitialization方法应用到该bean中,因为如果返回的bean不为空,那么便不会再次经历普通的bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法。下面是代码:

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

4.3、循环依赖

见《spring源码之:循环依赖

5、创建Bean

在经历了resolveBeforeInstantiation方法后,程序有两个选择,如果创建了代理或者说重写了InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法并在方法postProcessBeforeInstantiation中改变了bean,则直接返回就可以了,否则需要进行常规bean的创建,而常规bean的创建就是在AbstractAutowireCapableBeanFactory.java中定义的doCreateBean中完成的。

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException { BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//清除缓存1
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据指定bean使用对应的策略创建新的实例,如:工厂方法、构造函数自动注入、简单初始化2
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 {
     //3bean合并处理,Autowired注解正是通过此方法实现诸如类型的预解析
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
//4.依赖处理
//是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
//对bean的再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor,其中我们熟知的AOP
//就是在这里将advice动态织入到bean中,若没有则直接返回bean,不做任何处理
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} // Initialize the bean instance.
Object exposedObject = bean;
try {
//5.对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,则会递归初始依赖bean
populateBean(beanName, mbd, instanceWrapper);
//调用初始化方法,比如init-method
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);
}
}
//6.循环依赖检查
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//earlySingletonReference只有在检测到有循环依赖的情况下才会不为空
if (earlySingletonReference != null) {
//如果exposedObject没有在初始化方法中被改变,也就是没有被增强
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);
}
}
//因为bean创建后其所依赖的bean一定是已经创建的,actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有
//全部创建完,所以说存在循环依赖
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.");
}
}
}
} //7.根据scope注册bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
} return exposedObject;
}

尽管日志与异常的内容非常重要,但是在阅读源码的时候似乎大部分人都会直接忽略掉。在此不深入讨论日志及异常的设计,我们看看整个函数的概要思路。

(1)如果是单例则需要首先清除缓存

(2)实例化bean,将BeanDefinition转换为BeanWrapper :转换是一个复杂的过程,但是我们可以尝试概括大致的功能,如下所示

i.如果存在工厂方法则使用工厂方法进行初始化

ii.一个类有多个构造函数,每个构造函数都有不同的的参数,所以需要根据参数锁定构造函数并进行初始化

iii.如果既不存在工厂方法也不存在带有参数的构造方法,则使用默认的构造函数进行bean的实例化

(3)MergedBeanDefinitionPostProcessor的应用:bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析

(4)依赖处理:在Spring中会有循环依赖的情况,例如,当A中含有B属性,而B中又含有A的属性时就会构成一个循环依赖,此时如果A和B都是单例的,那么Spring中的处理方式就是当创建B时,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放在缓存中的ObjectFactory来创建实例,这样就解决了循环依赖的问题。对于循环依赖的讲解可以看一下这里

(5)属性填充:将所有属性填充至bean的实例中

(6)循环依赖检查:之前提到过,在Spring中解决循环依赖只对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常。在这个步骤龙里面会检测已经加载的bean是否已经出现了依赖循环,并判断是否需要抛出异常。

(7)注册DisposableBean。

(8)完成创建并返回。

可以看到上面的步骤非常的繁琐,每一步都使用了大量的代码来完成其功能,最复杂也是最难以理解的当属循环依赖的处理,在真正进入doCreateBean之前,我建议大家有必要先了解一下循环依赖。

6、创建Bean的实例

当我们了解了循环依赖以后就可以深入分析创建bean的每个步骤了,首先我们从AbstractAutowireCapableBeanFactory.java的createBeanInstance开始

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//解析class
Class<?> beanClass = resolveBeanClass(mbd, beanName); //bean的方法不为public,且不允许访问非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());
} Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
} //如果工厂方法不为空,则采用工厂方法初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
} // Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
//一个类中有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数确定构造函数或对应的工厂方法
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
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() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, args);
} //使用默认构造函数构造
return instantiateBean(beanName, mbd);
}

虽然代码中实例化的细节非常复杂,但是在createBeanInstance方法中我们还是可以清晰地看到实例化的逻辑。

(1)如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method,那么Spring会尝试使用instantiateUsingFactoryMethod(beanName, mbd, args)方法根据RootBeanDefinition中配置生成bean的实例

(2)解析构造函数并进行构造函数的实例化。因为一个bean对应的类中可能会有多少个构造函数,而每个构造函数的参数不同,Spring在根据参数及类型去最终判断会使用哪个构造函数进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod中。

6.1、autowireConstructor

对于实例的创建Spring中分成了两种情况,一种是通用的实例化,另一种是带有参数的实例化。带有参数的实例化过程相当复杂,因为存在着不确定性,所以在判断对应参数上做了大量工作。

ConstructorResolver.java

    protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
} public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw); Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null; //explicitArgs通过getBean方法传入,如果getBean方法调用的时候指定方法参数那么直接使用
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
//如果在getBean方法时候没有指定则尝试从配置文件中解析
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
//从缓存中获取
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);
}
} //没有被缓存
if (constructorToUse == null) {
// Need to resolve the constructor.
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.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);
} // Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
//排序给定的构造函数,public构造函数优先参数数量降序,非public构造函数参数数量降序
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.length > paramTypes.length) {
//如果已经找到选用的构造函数或者需要的参数个数小于当前构造函数参数个数则终止,因为是参数个数降序排列
break;
}
if (paramTypes.length < minNrOfArgs) {
//参数个数不相等
continue;
} ArgumentsHolder argsHolder;
if (resolvedValues != null) {
//有参数则根据值构造对应参数类型的参数
try {
//注释上获取参数名称
String[] paramNames = 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);
}
catch (UnsatisfiedDependencyException ex) {
if (this.beanFactory.logger.isTraceEnabled()) {
this.beanFactory.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 ArgumentsHolder(explicitArgs);
} //探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
//如果它代表当前最接近的匹配则选择作为构造函数
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.storeCache(mbd, constructorToUse);
}
} try {
final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
Object beanInstance; if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
beanFactory.getAccessControlContext());
}
else {
beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
//将构建的实例加入BeanWrapper
bw.setBeanInstance(beanInstance);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}

逻辑很复杂,函数代码量很大,包含着很多的逻辑实现,所以我们还是总览一下整个函数,其实现的功能考虑了一下几个方面

(1)构造函数参数的确定。

  • 根据explicitArgs参数类型判断

如果传入的参数explicitArgs不为空,那边可以直接确定参数,因为explicitArgs参数是在调用Bean的时候用户指定的,在BeanFactory中存在这样的方法:

Object getBean(String name, Object ... args) throws BeansException;

在获取bean的时候,用户不但可以指定bean的名称,还可以指定bean所对应类的构造函数或者工厂方法的方法参数,主要用于静态工厂方法的调用,而这里是需要给定完全匹配的参数的,所以,便可以判断,如果传入参数explicitArgs不为空,则可以确定构造函数参数就是它。对应代码:

if (explicitArgs != null) {
argsToUse = explicitArgs;
}
  • 缓存中获取

除此之外,确定参数的办法如果之前分析过,也就是说构造函数参数已经记录在缓存中,那么便可以直接拿来使用。而且,这里要提到的是,在缓存中缓存的可能是参数的最终类型也可能是参数的初始类型,例如:构造函数参数要求的说是int类型,但是原始的参数值可能是String类型的“1”,那么即使缓存中得到了参数,也需要经过类型转换器的过滤以确保参数类型与对应的构造函数参数类型完全对应。对应代码:

else {
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) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
  • 配置文件获取

如果不能根据传入的参数explicitArgs确定构造函数参数,也无法从缓存中得到相关信息,那么只能开始新一轮的分析了。

分析从获取配置文件中配置的构造函数信息开始,经过之前的分析,我们知道,Spring中配置文件的信息经过转换都会通过BeanDefinition实例承载,也就是mbd中包含,那么可以通过调用mbd.getConstructorArgumentValues()来获取配置的构造函数信息。有了配置中的信息便可以获取对应的参数值信息了,获取参数值的信息包括直接指定值,如:直接指定构造函数中摸个值为原始类型String类型,或者是对其他bean的引用,而这一处理委托给resolvedConstructorArguments方法,并返回能解析到的参数的个数。代码如下:

if (constructorToUse == null) {
// Need to resolve the constructor.
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.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);
}

(2)构造函数的确定。

经过了第一步已经确定了构造函数的参数,接下来的任务就是根据构造函数参数在所有构造函数中锁定对应的构造函数,而匹配的方法就是根据参数个数匹配,所以在匹配之前需要先对构造函数按照public构造函数优先参数数量降序、非public构造函数参数数量降序。这样可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件。

由于在配置文件中并不是唯一限制使用参数位置索引的方式去创建,同样还支持指定参数名称进行设定参数值的情况,如:<constructor-arg name="aa">,那么这种情况就需要首先确定构造函数中的参数名称。

获取参数名称可以有两种方式,一种是通过注解的方式直接获取,另一种是使用Spring中提供的工具类ParameterNameDiscover来获取。构造函数、参数名称。名称参数、参数类型、参数值都确定后就可以锁定构造函数以及转换对应的参数类型了。代码如下:

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.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;
}

(3)根据确定的构造函数转换对应的参数类型。代码如下:

if (resolvedValues != null) {
try {
String[] paramNames = 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);
}
catch (UnsatisfiedDependencyException ex) {
if (this.beanFactory.logger.isTraceEnabled()) {
this.beanFactory.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 ArgumentsHolder(explicitArgs);
}

主要是使用Spring中提供的类型转换器或者用户提供的自定义类型转换器进行转换。

(4)构造函数不确定性的验证。

当然,有时候即使构造函数、参数名称、参数类型都确定后也不一定会直接锁定构造函数,不同构造函数的参数为父子关系,所以Spring在最后又做了一次验证。代码如下:

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.storeCache(mbd, constructorToUse);
}

6.2、instantiateBean

经历了带有参数的构造函数的实例构造,再看不带参数的构造函数的实例化过程就会变的轻松加愉快了,下面是代码:

AbstractAutowireCapableBeanFactory.java

    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);
}
}

我们会发现,此方法没有什么实质性的的逻辑,带有参数的实例构造中,Spring把精力都放在了构造函数以及参数的匹配上,所以如果没有参数的话那将是一件非常简单的事情,直接调用实例化策略进行实例化就可以了。

6.3、实例化策略

实例化过程中反复提到过实例化策略,那这又是做什么用的呢?其实经过前面的分析,我们已经得到了足以实例化的所有相关信息,完全可以使用最简单的反射方法直接反射来构造实例对象,但是Spring却并没有这么做。来看一下代码:

SimpleInstantiationStrategy.java

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
//如果有需要覆盖或者动态替换的方法则需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
//但是如果没有需要动态改变的方法,为了方便直接反射就可以了
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
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);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

看了上面两个函数后似乎我们赢感受到了Spring的用心良苦以及为了能更方便的使用Spring而做的大量的工作。程序中,首先判断如果beanDefinition.getMethodOverrides()为空,也就是用户没有使用replace-method或者lookup-method配置,那么直接使用反射的方法,简单快捷,但是如果使用了这两个特性,在直接使用反射的方法创建就有些不妥了,因为需要将这两个配置提供的动能切入进去,所以必须要使用动态代理的方式将包含两个特性所对应的逻辑的拦截增强器设置进去,这样才可以保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。
记录创建bean的ObjectFactory

让我们继续回到doCreateBean方法中,在里面有这样一段代码:

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
//对bean的再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor,其中我们熟知的AOP
//就是在这里将advice动态织入到bean中,若没有则直接返回bean,不做任何处理
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

这段代码不是很复杂,但是很多人不是太理解这段代码的作用,而且,这段代码仅从此函数中去理解也很难弄懂其中的含义,我们需要从全军的角度去思考Spring的依赖解决办法。

  • earlySingletonExposure:从字面的意思理解就是提早曝光的单例,我们暂不定义它的学名叫什么,我们感兴趣的是有哪些条件影响这个值。
  • mbd.isSingleton():没有太多可以解释的,此RootBeanDefinition代表的是否是单例。
  • this.allowCircularReferences:是否允许循环依赖,很抱歉,并没有找到在配置文件中如何配置,但是在AbstractRefreshableApplicationContext中提供了设置函数,可以通过硬编码的方式进行设置或者可以通过自定义命名空间进行配置,其中硬编码的方式代码如下:
ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext("aspectTest.xml");
bf.setAllowBeanDefinitionOverriding(false);
  • isSingletonCurrentlyInCreation(beanName):该bean是否在创建中。在Spring中,会有专门的属性默认为DefaultSingletonBeanRegistry的singletonsCurrentlyInCreation来记录bean的加载状态,在bean开始创建前会将beanName记录在属性中,在bean创建结束后会将beanName从属性中移除。那么我们跟随代码一路走来可是对这个属性的记录并没有多少印象,这个状态是从哪里记录的呢?不同的scope的记录位置并不一样,我们以singleton为例,在singleton下记录属性的函数是在DefaultSingletonBeanRegistry类的getSingletone(String beanName, ObjectFactory singletonFactory)函数的beforeSingletonCreation(beanName)和afterSingletonCreation(beanName)中,在这两段函数中分别对属性进行了记录和移除。

经过以上分析我们了解变量earlySingletonExposure是否为true、是否是单例、是否允许循环依赖、是否对应的bean正在创建的条件的综合。当这几个条件同时满足时会执行addSingletonFactory操作,那么加入SingletonFactory的作用是什么呢?又是在什么时候调用呢?

我们还是以最简单的AB循环为例,类A中含有属性类B,而类B中又会含有属性类A,那么初始化beanA的过程如下图所示:

图中展示了创建beanA的流程,图中我们看到,在创建A的时候首先会记录类A所对应的beanName,并将beanA的创建工厂加入缓存中,而在对A的属性填充也就是调用populateBean方法的时候又会再一次的对B进行递归创建。同样的,因为在B中同样存在A属性,因此在实例化B的populate方法中又会再次的初始化B,也就是图形的最后,调用getBean(A)。关键是这里,有心的读者可以去找找这个代码的实现方式,我们之前已经讲过,在这个函数中并不是直接去实例化A,而是先去检测缓存中是否有已经创建好的对应的bean,或者是否已经创建好的ObjectFactory,而此时的ObjectFactory我们早已创建,所以便不会再去向后执行,而是直接调用ObjectFactory去创建A。这里最关键的是ObjectFactory的实现。根据以上分析,基本可以理清Spring处理循环依赖的解决办法,在B中创建依赖A时通过ObjectFactory提供的实例化方法来中断A中的属性填充,使B中持有的A仅仅是刚刚初始化并没有填充任何属性的A,而初始化A的步骤是在最开始创建A的时候进行的,但是因为A与B中的A所表示的属性地址是一样的,所以A中创建好的属性填充自然可以通过B中的A获取,这样就解决了循环依赖的问题。也正是由于ObjectFactory提供的实例是初始化状态下的实例,所以构造器构造bean的循环依赖Spring是无法解决的,同样,由于属性地址的问题,在非单例模式下,两个实例的地址不一定相同,所以Spring也无法解决这种情况下的循环依赖。

6.3、属性注入

在了解循环依赖的时候,我们曾经反复提到了populateBean这个函数,也多少了解了这个函数的主要功能就是属性填充,那么究竟是如何填充的呢?

AbstractAutowireCapableBeanFactory.java

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
//没有可填充的属性
return;
}
} //给InstantiationAwareBeanPostProcessors最后一次机会再属性设置前改变bean
//如:可以用来支持属性注入的类型
boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//返回值为是否继续填充bean
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
} //如果后处理器发出停止填充命令则终止后续的执行
if (!continueWithPropertyPopulation) {
return;
} PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs); //根据名称自动注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
} //根据类型自动注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
} pvs = newPvs;
} //后处理器已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//对所有需要依赖检查的属性进行后处理
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
//依赖检查,对应depends-on属性,3.0已经弃用此功能
checkDependencies(beanName, mbd, filteredPds, pvs);
}
} if (pvs != null) {
//将属性应用到bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

在populateBean函数中提供了这样的处理流程。

(1)InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数的应用,此函数可以控制程序是否需要进行属性填充。

(2)根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中。

(3)应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理,典型应用是RequiredAnnotationBeanPostProcessor类中对属性的验证。

(4)将所有PropertyValues中的属性填充至BeanWrapper中。

在上面的步骤中有几个地方是我们比较感兴趣的,它们分别是依赖注入以及属性填充,那么,接下来进一步分析这几个功能的实现细节。

1、autowireByName

上文提到根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中,那么我们首先了解下byName功能是如何实现的

AbstractAutowireCapableBeanFactory.java

    protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { //寻找bw中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//递归初始化相关的bean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
//注册依赖
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}

如果大家之前了解了autowire的使用方法,相信理解这个函数的功能不会太困难,无非是在传入参数pvs中找出已经加载的bean,并递归实例化,进而加入到pvs中。

2、autowireByType

autowireByType与autowireByName对于我们理解与使用来说复杂程度都很相似,但是其实现功能的复杂度却完全不一样

AbstractAutowireCapableBeanFactory.java

    protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
} Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//寻找bw中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
if (Object.class != pd.getPropertyType()) {
//探测指定属性的set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd)
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowiredBeanNames中,当属性存在多个封装的bean时
//比如@Autowire private List<A> aList;将会找到所有匹配A类型的bean并将其注入
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//注册依赖
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}

实现根据名称自动匹配的第一步就是寻找bw中需要依赖注入的属性,同样对于根据类型自动匹配的实现来讲第一步也是寻找bw中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的bean,其中最复杂的就是寻找类型匹配的bean。同时,Spring中提供了对集合注入的支持,比如使用注解的方式:

@Autowired
private List<TestA> tests;

Spring将会把所有与Test匹配的类型找出来并注入到tests属性中,正是由于这一因素,所以在autowireByType函数中,新建了局部遍历autowiredBeanNames,用于存储所有依赖的bean,如果只是对非集合类的属性注入来说,此属性并无用处。

对于寻找类型匹配的逻辑实现封装在了resolveDependency函数中

    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
//Optional类注入的特殊处理
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
//ObjectFactory和ObjectProvider类注入的特殊处理
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
//javaxInjectProviderClass类注入的特殊处理
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//通用处理逻辑
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}

上面的的代码的注释中已经提到了,Spring5.0相比Spring3.0在代码上做出的改进,将原本代码中处理Array、Collection和Map的处理逻辑全部放进了一个新的方法resolveMultipleBeans中,这样就避免了我们之前看到的Spring中的某些代码过长,导致逻辑层次不是很清晰的问题。

寻找类型匹配执行顺序时,首先尝试使用解析器进行解析,如果解析器没有成功解析,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器,但是对于集合类型来说并不在解析范围之内,所以再次对不同类型进行不同情况的处理,虽说对于不同类型处理方式不太一致,但是大致的思路还是很相似的,所以函数中只对数组类型进行了详细的注释。

3、applyPropertyValues

程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以PropertyValues形式存在的,还并没有应用到已经实例化的bean中,这一工作是在applyPropertyValues中完成的。下面是代码:

    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
} if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
} MutablePropertyValues mpvs = null;
List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
//如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanWrapper中
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
//如果pvs并不是使用MutablePropertyValues封装的类型,那么直接使用原始的属性获取方法
original = Arrays.asList(pvs.getPropertyValues());
} TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//获取对应的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); //深拷贝
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
//遍历属性,将属性转换为对应类的对应属性的类型
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
} // Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}

6.4、初始化bean

大家应该记得bean配置时bean中有一个init-method属性,这个属性的作用是在bean实例化前调用init-method指定的方法来根据用户业务进行相应的实例化。我们现在就已经进入这个方法了,首先看一下这个方法的执行位置,Spring中程序已经执行过bean的实例化,并且进行了属性的填充,而就在这时会调用用户设定的初始化方法。

AbstractAutowireCapableBeanFactory.java

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//对特殊的bean处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
} Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//应用后处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
} try {
//激活用户自定义的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//后处理器的应用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
} return wrappedBean;
}

虽说此函数的主要目的是进行客户设定的初始化方法的调用,但是除此之外还有其他必要的工作。

6.4.1、激活Aware方法

在分析其原理之前,我们先了解一下Aware的使用。Spring中提供了一些Aware相关接口,比如BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等、实现这些Aware接口的bean在被初始之后,可以取得一些相对应的资源,例如实现BeanFactoryAware的bean在初始化后,Spring容器将会注入BeanFactory的实例,而实现ApplicationContextAware的bean,在bean被初始化后,将会被注入ApplicationContext实例等,我们首先通过示例方法来了解一下Aware的使用。

(1)定义普通bean。

public class Hello{
public void say(){
System.out.println("hello");
}
}

(2)定义BeanFactoryAware类型的bean

public class Test implements BeanFactoryAware{
private BeanFactory beanFactory; //声明bean的时候Spring会自动注入BeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeanException{
this.beanFactory = beanFactory;
} public void testAware(){
//通过hello这个bean id从beanFactory中获取实例
Hello hello = (Hello)beanFactory.getBean("hello");
hello.say();
}
}

(3)使用main方法测试

public static void main(Stirng[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Test test = (Test)ctx.getBean("test");
test.testAware();
}

运行测试类,控制台输出:hello

按照上面的方法我们可以获取到Spring中BeanFactory,并且可以根据BeanFactory获取所有bean,以及进行相关设置。当然还有其他Aware的使用方法都大同小异,看一下,Spring的实现方式,相信大家便会使用了。下面是代码:

AbstractAutowireCapableBeanFactory.java

    private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

代码非常简单,没有什么可说的...

2、处理器的应用

BeanPostProcessor相信大家都并不陌生,这是Spring中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或扩展Spring,而除了BeanPostProcessor外还有很多其他的PostProcessor,当然大部分都是以此为基础,继承自BeanPostProcessor。BeanPostProcessor的使用位置就是这里,在调用客户之定义初始化方法前以及调用自定义初始化方法后分别会调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法,使用户可以根据自己的业务需求进行响应的处理。

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
} public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

3、激活自定义的init方法

客户定制的初始化方法除了我们熟知的使用配置init-method外,还有使自定义的bean实现InitializingBean接口,并在afterPropertiesSet中实现自己的初始化业务逻辑。

init-method与afterPropertiesSet都是在初始化bean时执行,执行顺序是afterPropertiesSet先执行,而init-method后执行。在invokeInitMethods方法中就实现了这两个步骤的初始化方法调用。

    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable { //首先检查是否是InitializingBean,如果是的话需要afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//属性初始化后处理
((InitializingBean) bean).afterPropertiesSet();
}
} if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//调用自定义初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

注册DisposableBean

Spring中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口,对于销毁方法的扩展,除了我们熟知的配置属性destroy-method方法外,用户还可以注册后处理器DestructionAwareBeanPostProcessor来统一处理bean的销毁方法,代码如下

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
//单例模式下注册需要销毁的bean,此方法中会处理实现DisposableBean的bean
//并且对所有的bean使用DestructionAwareBeanPostProcessor处理
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
//自定义scope处理
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}

至此,用BeanFactory方式创建和获取bean的流程我们就彻底分析完了,但是在实际的代码中,我们是很少会使用BeanFactory这种方式去获取bean。通常我们使用的是ApplicationContext来获取,这俩者究竟有什么区别,我们又为什么选择后者,这些将在下一篇文章中了解到。

转:https://blog.csdn.net/vergilsmallshoes/article/details/80652184
转:https://www.jianshu.com/p/fa81c043b3a9

python的装饰器的更多相关文章

  1. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  2. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  3. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  4. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  5. 两个实用的Python的装饰器

    两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...

  6. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  7. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  8. python基础—装饰器

    python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...

  9. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  10. 关于python的装饰器(初解)

    在python中,装饰器(decorator)是一个主要的函数,在工作中,有了装饰器简直如虎添翼,许多公司面试题也会考装饰器,而装饰器的意思又很难让人理解. python中,装饰器是一个帮函数动态增加 ...

随机推荐

  1. Unity. Navigation和寻路

    Navigation Static:不会移动.可以用于计算可行走区域.例如:地板.墙.静态障碍物. 将一个物体选为Navigation Static:Navigation窗口-> 勾选项

  2. Intent的详细解析以及用法

    Intent的详细解析以及用法      Android的四大组件分别为Activity .Service.BroadcastReceiver(广播接收器).ContentProvider(内容提供者 ...

  3. 宝洁的Pvp

    1.公司宗旨(Purpose) 我们生产和提供更佳品质及价值的产品,以改善全球消费者的生活.作为回报,我们将会获得领先的市场销售地位和利润增长,从而令我们的员工.我们的股东以及我们的生活.工作所处的社 ...

  4. python数据分析之pandas库的Series应用

    一.pandas的数据结构介绍 1. Series 1.1 Series是由一种类似于一维数组的对象,它由一组数据以及一组与之相关的数据索引构成.仅由一组数据可产生最简单的Series. from p ...

  5. java读取properties文件的内容

    获得properties文件中某个key对应着的value // 路径名称 + properties的名称,不要“properties” private static final String BUN ...

  6. WPF Image控件使用本地图片

    BitmapImage bi = new BitmapImage(); // BitmapImage.UriSource must be in a BeginInit/EndInit block. b ...

  7. CSS position, z-index

    position 1.fixed:定位.浮动.(需要搭配left, right) 2.absolute:相对于最近的父元素,不考虑周围的布局.(可使用z-index占据位置,则同一位置层叠) 3.re ...

  8. 剑指offer系列55---最小的k个数

    [题目] 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. *[思路]排序,去除k后的数. package com.exe11 ...

  9. TX Textcontrol 使用总结五——添加图片

    实现如图所示效果: 实现代码如下所示: 注意,此处不做代码格式化处理... using System;using System.Collections.Generic;using System.Dra ...

  10. metaspolit教程

    网上的安装方式都是抄来抄去,我也抄了下,不过好歹自己试了下,有所不同 git clone https://github.com/rapid7/metasploit-framework.git vim ...