目录
一、不同scope实例创建的简单分析
1、单例对象创建
getSingleton(String beanName,ObjectFactory of)方法详解
2、原型对象创建
3、其他Scope范围bean实例创建
二、创建bean实例的核心流程分析
1、creatBean()方法
2、doCreateBean()方法
3、 createBeanInstance()
3.1、使用Supplier函数接口进行bean的实例化
3.2、 使用工厂方法进行bean的实例化
3.3、使用构造函数进行bean的实例化
前言:我们在上一篇博文 spring源码分析之bean的加载 中已经介绍了有关spring的bean加载过程中的主要流程,只是在创建不同scope范围的bean实例的过程中留下了伏笔,那么这边博文作者针对其上面博文有关手动创建bean实例进行详细的介绍。
先简单补充一下实例创建的代码
逻辑代码:单例对象使用beanFactory的重载重载方法 getSingleton(String beanName,ObjectFactory of)。
ObejctFactory是一个接口式接口,这里使用了匿名内部类 调用createBean()方法 具体的创建bean实例的正式该方法。
//创建单例对象代码片段
sharedInstance = getSingleton(beanName, () -> {
try {
//具体的调用逻辑是调用ObjectFactory其匿名内部类的getObject()方法
//方法中createBean()方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
/**
* 创建单例对象
* @param beanName 创建对象的beanName
* @param singletonFactory 具体调用该对象的getObject()方法创建对应的bean实例
* @return 返回创建的对象
*/
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//从单例缓存中获取单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果对象为null
if (singletonObject == null) {
//则进行单例对象的创建操作
//判断如果该beanFactory被销毁则抛出异常
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException();
}
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<>();
}
try {
//调用ObjectFactory 创建实例对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
//在创建对象的时候出现异常 可能从别的途径隐式的创建对象 所有从缓存中获取
// 看看是否有了,破罐子破摔
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
//添加创建bean实例异常的信息
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//单例对象创建之前的回调 默认实现将正在创建的该bean标识
//从正在创建bean的列表中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//添加新创建的单例对象到缓存中
addSingleton(beanName, singletonObject);
}
}
//返回创建的单例对象
return singletonObject;
}
创建原型对象的核心逻辑和单例创建实例一致调用createBean()方法
//原型对象创建的代码逻辑
Object prototypeInstance = null;
try {
//原型对象创建之前的回调
//主要功能是将创建的beanName 放入prototypesCurrentlyInCreation中
beforePrototypeCreation(beanName);
//创建原型对象的方式和创建单例对象的一样 这里不再详述
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//原型对象创建之前的回调
//主要功能是将创建的beanName从prototypesCurrentlyInCreation移除
afterPrototypeCreation(beanName);
}
调用scope的get(String beanName,ObjectFactory of), get()方法中调用ObjectFactory的getObject() 创建对象实例,最终调用和上面的创建bean实例流程一致调用creatBean()方法
//调用scope的get方法,具体的创建的操作是在其第二个匿名参数ObjectFactory
//里面也是调用createBean()
Object scopedInstance = scope.get(beanName, () -> {
//与原型对象创建之前的回调一致
//标记该beanName对应的bean实例对象正在被创建
beforePrototypeCreation(beanName);
try {
//具体创建bean实例的核心代码
return createBean(beanName, mbd, args);
}
finally {
//与原型对象创建之后的回调一致
//移除beanName对应的bean实例从标记中
afterPrototypeCreation(beanName);
}
});
//scope 获取对象的
public Object get(String name, ObjectFactory> objectFactory) {
//先从缓存中获取对应的bean实例 如果没有则调用ObjectFactory的getObject()方法
//getObject()方法中的实现是上面匿名内部类的createBean()方法
Map scope = (Map)this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
scope.put(name, scopedObject);
}
return scopedObject;
}
对于上面三种类型bean实例创建,各有不同点,但是最终都是调用相同的createBean()来进行实例的创建。下面我们来分析三种创建bean实例的核心代码createBean()方法。
//根据RootBeanDefinition 创建对应的bean实例
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;
//1、解析beanDefinition中获取其中的class属性
//如果beanDefinition中没有填充class属性
//填充对应的RootBeanDefinition 的BeanClass
Class> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass()
&& mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
//2、在beans.xml 中replace-method、lookup 配置
//会被解析到BeanDefinition的MethodOverride中
//标记BeanDefintion中的某些MethodOverride 只有一个方法 标明该方法没有重载方法
//在进行methodOverrides实例化的时候避免参数检查的开销
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(ex);
}
try {
//3、通过应用bean的后置处理器 返回一个代理对象而非目标对象,
//此处是我们常用的AOP功能的实现
//这里有一个短路操作 如果代理对象存在则直接返回代理对象 不在做后续的操作
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(ex);
}
try {
//4、对于普通的bean 实例执行真正的创建bean实例的逻辑
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
//返回bean实例对象
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex)
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(ex);
}
}
上面代码的主要逻辑如下:
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
//判断beanDefintion是否有MethodOverrides
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
//获取class中 方法名对应的重载方法的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException();
}
//如果重载方法个数为1 则说明该方法没有重载方法 设置MethodOverride 的重载标识为false
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}
//应用后置处理器,对bean实例进行代理增强 我们的AOP代理增强也是在该处来进行实现
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//获取bean的class实例
Class> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//应用bean实例化之前的后置处理器进行 bean的处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//应用bean实例化之后的后置处理器进行 bean的处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
在上面代码对createBean()分析发现,对于普通bean实例的创建是由doCreatBean()来实现的接下来我们来分析doCreateBean()方法。
//真正的创建bean操作
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
//BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,
// 获取被包装bean的属性描述器,由于BeanWrapper接口是PropertyAccessor的子接口,
// 因此其也可以设置以及访问被包装对象的属性值。
BeanWrapper instanceWrapper = null;
//单例对象
if (mbd.isSingleton()) {
//先从缓存中获取BeanWrapper 并移除缓存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据对应的策略创建新实例 工厂方法 构造函数 等创建实例
//实例化bean 将BeanDefinition转换为BeanWrapper
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//获取对应的bean实例
final Object bean = instanceWrapper.getWrappedInstance();
//获取对应的bean 的class属性
Class> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
//设置beanDefintion的class属性resolvedTargetType
mbd.resolvedTargetType = beanType;
}
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//应用MergedBeanDefinitionPostProcessor后置处理器
//主要是对AutowiredAnnotation、通用注解进行后置处理器
//比如 AutowiredAnnotationBeanPostProcessor类把正在被spring实例化的bean
//进行@Autowired和@Value扫描,
//扫描到类里面属性和方法上面如果有注解,就会把对应的方法或者属性封装
//最终封装成InjectionMetadata对象
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(ex);
}
mbd.postProcessed = true;
}
}
//为了解决循环依赖 先将实例化的bean此时还未初始化包装成ObjectFactory
//添加到singletonFactories缓存中
//正在初始化化的单例模式的bean(已经实例化)为了避免循环引用先想将其包装成
//ObjectFactory放入缓存中 提前暴露出去。
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//在该bean实例未完全初始化之前 先将其包装为ObjectFactory对象放入缓存暴露出去
addSingletonFactory(beanName,
() -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
//前面已经实例化了bean 接下来初始化bean实例
populateBean(beanName, mbd, instanceWrapper);
//如果bean实例继承了XXXAware 调用其对对应的接口类设置属性
//或者调用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);
}
}
//如果该实例bean已经提前暴露出来
if (earlySingletonExposure) {
//说明该bean实例至少已经加载到了缓存中
//如果调用initializeBean() exposedObject和bean一致
//则说明exposedObject没有被改变
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping
&& hasDependentBean(beanName)) {
//获取beaName的依赖 beanName依赖一定是创建的 (先创建依赖bean 再创建BeanName)
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet<>
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//如果actualDependentBeans 说明还有beanName对应的依赖没有创建完成
//有循环依赖
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException();
}
}
}
}
// Register bean as disposable.
try {
//spring对于bean实例的销毁方法 除了使用destory-method
//还可以通过注册DestructionAwareBeanPostProcesser 来统一处理bean的销毁方法
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(ex);
}
return exposedObject;
}
通过上述的一系列步骤最终创建出来我们想要的bean实例了。
createBeanInstance() 获取对应的bean实例对象并将其包装成BeanWarpper
populateBean() 填充实例bean的相关属性
initializeBean() 调用bean实例的相关初始化方法 比如init-method,XXXAware接口等
registerDisposableBeanIfNecessary()为创建的实例bean注册销毁方法。bean实例被销毁的时候会调用注册的销毁方法
在上面bean实例化过程中我们概览了bean实例化的大致流程,但是对于bean实例化细节,并没有过多的介绍,对于bean实例化的细节其实是在createBeanInstance()方法中,该方法主要根据对应的策略创建新实例,比如工厂方法、构造函数等方式创建实例。下面我们来分析下代码片段
//具体的对beanDefintion进行处理 并通过不同的方式实例化bean 譬如工厂、特定构造器 默认构造器等
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 获取对应的mbd的class属性
Class> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers())
&& !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException();
}
//1、Spring5.0新增的实例化策略,如果设置了该策略,将会覆盖构造方法和工厂方法实例化策略
//Supplier 一个通过get()方法创建对象的
//如果对应的beanDefinition 由Supplier 则调用其get方法获取bean实例
Supplier> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 后面根据bean创建的不同方式 默认构造器实例化、特定构造器实例化、工厂方式创建
// 由AbstractAutowireCapableBeanFactory 委托给ConstructorResolver调用其相应的方法
// 1、如果使用工厂方法 则调用ConstructorResolver的instantiateUsingFactoryMethod()
//来调用工厂类的静态/非静态方法初始化
// 2、如果有特定构造器 则调用ConstructorResolver的autowireConstructor() 方法
//默认构造器实例化bean
// 3、否则使用默认空构造器函数实例化bean
//调用工厂方法进行实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// bean对应的类可能会有多个构造函数,而每个构造函数的参数不同
// spring在根据参数以及类型去判断最终使用哪个构造函数进行实例化
//但是构造参数判断的过程比较耗时 这里会使用缓存机制
//先尝试从缓存中获取已经解析的构造函数方法
//如果没有则进行判断并将判断出来的构造函数方法放入缓存中便于下来使用。
//单例模式: spring针对单例模式只创建一次将其实例化用到的构造函数方法存入缓存有什么意义
// 我们知道对于IoC容器除了可以获取bean之外,还能销毁bean,
// 当我们调用BeanFactory.destroyBean(myBeanName,myBeanInstance),
// 销毁bean时,容器是不会销毁已经解析的构造函resolvedConstructorOrFactoryMethod的,
// 如果再次调用BeanFactory.getBean(myBeanName)时,就会使用缓存的实例化构造器方法了。
//原型模式: 对于该模式的理解就简单了,IoC容器不会缓存原型模式bean的实例,
/ /当我们第二次向容器索取同一个bean时,就会使用该缓存的实例化构造函数方法了。
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
//说明以前解析过该bean对应的构造函数
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() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//判断出来了需要使用的构造器 使用构造器进行初始化
return autowireConstructor(beanName, mbd, ctors, args);
}
// 没有查找到对应的构造函数 则使用默认的构造函数构造
return instantiateBean(beanName, mbd);
}
上面的代码虽然比较多,但是相对简单,主要分三种情况描述bean实例化
Spring5.0新增的实例化策略,如果设置了该策略,将会覆盖构造方法和工厂方法实例化策略 。在bean注册成BeanDefintion会调用registerBean(beanName, beanClass, Supplier
//通过给定的Supplier 调用其get()方法获取一个bean实例 并将其包装为BeanWrapper
protected BeanWrapper obtainFromSupplier(Supplier> instanceSupplier, String beanName) {
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
Object instance;
try {
//调用Supplier的get()获取bean实例
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
//将实例bean包装成BeanWrapper对象
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
工厂方法创建主要分成两种:一种是使用工厂的静态方法创建bean实例,另一种是工厂的非静态方法创建bean实例。
//调用该bean对应的factory-method 来实现化bean实例
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
//构建一个BeanWrapperImpl 实例并注册到beanFactory中
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class> factoryClass;
boolean isStatic;
//获取beanDefintion的FactoryBeanName
// 注意:静态工厂方法是没有factoryBeanName的,
// 所以如果factoryBeanName不为null,则一定是实例工厂方法,
// 否则就是静态工厂方法
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
//工厂名字不能和beanName相同 工厂对象不能生产自己本身
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException();
}
//先获取工厂对象实例
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
//获取工厂对象class
factoryClass = factoryBean.getClass();
//表明使用非静态的方式创建对象
isStatic = false;
}
else {
//使用工厂类的静态方法获取实例对象
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException();
}
factoryBean = null;
//class属性为beanDefintion的beanClass属性
factoryClass = mbd.getBeanClass();
//表明使用静态的方式创建对象
isStatic = true;
}
//调用工厂的具体方法对象
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//2、判断有无显式指定构造方法参数,如果有则优先使用
// 如xmlBeanFactory.getBean("student", "张同学","13岁");
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//获取以及解析过的工厂方法以及该方法对应的参数
//因为解析对应的FactoryMethod 是一个比较耗时的操作 这里如果曾经解析过
//则会放到beanDefintion的对应的属性中便于下次初始化的时候直接使用
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
//从beanDefinition的属性中获取对应的解析参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
//解析参数类型,如果获取到的构造函数为A(int a,int b)
// 会将对应的参数类型A("1","2") 转换为A(1,2)类型
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw,
factoryMethodToUse, argsToResolve);
}
}
//如果工厂方法 或者参数为null(不是size 为0) 则FactoryMethod相关属性没有被解析
if (factoryMethodToUse == null || argsToUse == null) {
//这里需要去判断合适的工厂方法
factoryClass = ClassUtils.getUserClass(factoryClass);
//判断的依据是mbd.isNonPublicAccessAllowed()是否允许私有方法被访问
// 允许则获取factoryClass的所有方法、不允许则只获取其公有方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List candidateList = new ArrayList<>();
//遍历所有的方法 如果满足条件isStatic、mbd的factoryMethod一致的方法
//放入candidateList中 侯选者列表中
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic
&& mbd.isFactoryMethod(candidate)) {
candidateList.add(candidate);
}
}
Method[] candidates = candidateList.toArray(new Method[0]);
//排序侯选者方法列表 优先选择公有工厂方法和参数最多的方法
//(贪婪算法 参数越多 包容性越强越容易匹配上)
AutowireUtils.sortFactoryMethods(candidates);
ConstructorArgumentValues resolvedValues = null;
//判断mbd注入方式是否构造器注册
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set ambiguousFactoryMethods = null;
//定义最小工厂方法参数个数,以备循环解析候选方法使用
int minNrOfArgs;
//如果显示的指定了参数 则使用指定的参数的构造方法
if (explicitArgs != null) {
//如指定参数不为空,则使用指定参数个数作为最小方法参数个数
minNrOfArgs = explicitArgs.length;
}
else {
//如果没有显示的指定参数信息,尝试从beanDefintion中解析构造函数信息
//以便确定参数个数最少的构造函数
if (mbd.hasConstructorArgumentValues()) {
//获取beanDefintio中保存的构造函数参数信息
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//要为beanDefintio中保存的构造函数参数列表解析特定的参数信息
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
//以上均未能获取,则将最小方法参数个数置为0
minNrOfArgs = 0;
}
}
LinkedList causes = null;
for (Method candidate : candidates) {
Class>[] paramTypes = candidate.getParameterTypes();
//这里只获取候选方法的参数格式大于等于最少参数格式的候选方法
//不满足最少参数个数的方法会被排除掉
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
//如果有显示声明的构造参数 候选方法的参数个数必须完全匹配显示参数个数
//换句话说 要找到完全匹配显示参数个数的构造方法
if (explicitArgs != null) {
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
//解析构造参数 通过类型转换或者自动装配 创建参数持有者ArgeHolder
try {
String[] paramNames = null;
ParameterNameDiscoverer pnd =
this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
argsHolder = createArgumentArray(
beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
candidate, autowiring);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
//
}
}
//通过构造函数参数权重对比,得出最适合使用的构造函数
//先判断是返回是在宽松模式下解析构造函数还是在严格模式下解析构造函数。(默认是宽松模式)
//对于宽松模式:例如构造函数为(String name,int age),配置文件中定义(value="张同学",value="18")
//那么对于age来讲,配置文件中的"3",可以被解析为int也可以被解析为String,
//这个时候就需要来判断参数的权重,使用ConstructorResolver的静态内部类
//ArgumentsHolder分别对字符型和数字型的参数做权重判断,权重越小,则说明构造函数越匹配
//对于严格模式:严格返回权重值,不会根据分别比较而返回比对值
// 注意:minTypeDiffWeight = Integer.MAX_VALUE;而权重比较返回结果都是
// 在Integer.MAX_VALUE做减法,起返回最大值为Integer.MAX_VALUE
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// 如果未能明确解析出需要使用的工厂方法
//对于具有相同参数个数的方法,如果具有相同类型的权值,则收集这些候选对象,并最终引发歧义异常。
// 但是,只在非宽松的构造函数解析模式中执行该检查,并显式地忽略覆盖的方法(具有相同的方法)。
//该行代码是在 大的条件语句factoryMethodToUse 是null的条件下 中间没有想过赋值操作
//代码不会执行吧?
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) {
//如果有异常信息 则为beanFacotry添加创建该bean异常信息 并抛出异常
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
//如果没有异常信息 则讲所有的参数简单的名字收集起来
//并使用该参数信息去抛出BeanCreationException详细异常信息
List argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set 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();
}
//如果工厂方法的return 为void 抛出异常
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException();
}
//如果有有歧义的方法 抛出异常
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException();
}
//判断后最终确定的构造函数存储在beanDefintion中方便下次使用的时候
// 不用进行耗时的判断操作 直接使用即可
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
try {
Object beanInstance;
//这里才是我们调用工厂方法的具体逻辑
//获取beanFactory的具体的实例化策略 进行bean的实例化
if (System.getSecurityManager() != null) {
final Object fb = factoryBean;
final Method factoryMethod = factoryMethodToUse;
final Object[] args = argsToUse;
beanInstance = AccessController.doPrivileged((PrivilegedAction
上面的代码很多也很复杂,主要的逻辑为先判断创建工厂对象的使用静态方法还是非静态方法,获取工厂对应的所有方法,根据方法名和参数个数匹配到最适合的方法最终合适的工厂方法创建实例对象。最終通过InstantiationStrategy类的instantiate()方法来进行实例化 Object result = factoryMethod.invoke(factoryBean, args)反射实例化。
使用构造函数和使用工厂方法进行bean实例化逻辑相同,唯一的区别构造器形式进行bean的实例化需要根据参数个数和类型匹配对应的构造函数,通过反射进行实例化。
//和使用工厂方法实例化bean的逻辑相同 只不过此处是判断匹配的构造器方法 而非工厂方法
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor>[] chosenCtors, @Nullable Object[] explicitArgs) {
//1、创建一个默认的bean实例的包装类BeanWrapperImpl实例
// 用来承接我们实例化的bean
BeanWrapperImpl bw = new BeanWrapperImpl();
//对BeanWrapperImpl实例初始化并将其作为PropertyEditorRegistry注册到beanFactory
this.beanFactory.initBeanWrapper(bw);
//用来存储判断出来的需要使用的构造函数
Constructor> constructorToUse = null;
//用来存储判断出来的需要使用的构造函数参数对象(持有者)
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//2、判断有无显式指定构造方法参数,如果有则优先使用
// 如xmlBeanFactory.getBean("student", "张同学","13岁");
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
//3、从缓存中尝试获取解析的构造函数方法
else {
Object[] argsToResolve = null;
//获取以及解析过的工厂方法以及该方法对应的参数
//因为解析对应的构造函数Constructor对象 是一个比较耗时的操作 这里如果曾经解析过
//则会放到beanDefintion的对应的属性中便于下次初始化的时候直接使用
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;
}
}
}
//解析参数类型,如果获取到的构造函数为A(int a,int b)
//会将对应的参数类型A("1","2")转换为A(1,2)类型
if (argsToResolve != null) {
//缓存中的值可能是原始值 也可能是最终值 原始值需要进行解析
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
//4、如果缓存中没有说明构造器函数没有被解析存储到beanDefintion的缓存中
//这里需要来进行解析构造器参数并判断使用哪个构造器参数
if (constructorToUse == null) {
// 判断注入方式为构造器函数注入
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
//用来引用解析后的构造函数参数列表
ConstructorArgumentValues resolvedValues = null;
//定义最小构造函数参数个数,以备循环解析候选方法使用
int minNrOfArgs;
if (explicitArgs != null) {
//如指定参数不为空,则使用指定参数个数作为最少构造方法参数个数
minNrOfArgs = explicitArgs.length;
}
else {
//否则从beanDefintion中的获取构造参数对象 以及最少构造方法参数个数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
//用来承接 resolveConstructorArguments()方法解析后的构造参数对象
//该方法会解析参数信息 比如获取参数的基本类型 或者一个引用类型 并返回解析到的参数个数
//该参数个数也是我们去匹配候选构造函数的最低参数个数
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//5、根据构造参数 来确定对应的构造函数
// 将外部传入显示的构造方法对象列表 先作为候选构造函数列表中
Constructor>[] candidates = chosenCtors;
//如果外部传入的候选构造函数为null 需要我们来解析出候选构造函数
if (candidates == null) {
//获取创建bean实例的class属性
Class> beanClass = mbd.getBeanClass();
try {
//根据beanClass属性 获取其全部的构造函数
//判断的依据是mbd.isNonPublicAccessAllowed
// 是否允许私有构造方法被访问
// 1、允许则获取beanClass的所有构造方法方法、
// 2、不允许则只获取其公有构造方法方法
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);
}
}
//6、排序侯选者构造方法列表 优先选择公有构造方法和参数最多的构造方法
// (贪婪算法 参数越多 包容性越强越容易匹配上)
AutowireUtils.sortConstructors(candidates);
//这里如果有多个侯选者构造方法 需要使用权重大小来匹配合适的构造器函数
//权重越小则越匹配 还涉及到宽松模式和非狂送模式
int minTypeDiffWeight = Integer.MAX_VALUE;
//有歧义的构造函数方法 出现匹配的构造函数有多个的歧义
// 如果有会收集到这里 在后面如果有则抛出歧义异常信息
Set> ambiguousConstructors = null;
//实例化过程中的异常信息存储类
LinkedList causes = null;
//遍历所有侯选者构造函数列表
for (Constructor> candidate : candidates) {
// 1、获取构造函数的参数类型
Class>[] paramTypes = candidate.getParameterTypes();
//我没看错的话 这段代码是在if(constructorToUse==null)的条件下判断的
//这行代码怎么会执行呢?
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;
}
//2、获取构造函数的参数名称
//用于存储构造参数信息的对象(构造函数参数持有者)
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {
//如果候选的构造函数有注解@ConstructorProperties修饰
// 获取其中的names 作为参数名列表
//因为参数生成 有两种方式 一种是根据索引indexedArgumentValues map集合
// 一种是根据名字genericArgumentValues map集合
//所以针对参数 需要使用ParameterNameDiscoverer 获取参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
//如果没有注解修饰的参数 则获取工厂对象的构造参数查找器(作用是获取构造函数的参数名称)
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//通过ParameterNameDiscoverer的getParameterNames()方法
//获取构造函数的参数名称
paramNames = pnd.getParameterNames(candidate);
}
}
//将获取到的构造参数转换ArgumentsHolder对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring);
}
//异常 添加到异常中causes
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
//对于外部显示的参数 构造函数对应的参数个数必须完全匹配
//已经显示的指定了构造参数 所以需要获取与其参数完全匹配的构造函数
if (paramTypes.length != explicitArgs.length) {
continue;
}
//将显示的外部构造参数 包装成ArgumentsHolder对象
argsHolder = new ArgumentsHolder(explicitArgs);
}
//通过构造函数参数权重对比,得出最适合使用的构造函数
// 先判断是返回是在宽松模式下解析构造函数还是在严格模式下解析构造函数。(默认是宽松模式)
// 对于宽松模式:例如构造函数为(String name,int age),配置文件中定义(value="张同学",value="18")
// 那么对于age来讲,配置文件中的"3",可以被解析为int也可以被解析为String,
// 这个时候就需要来判断参数的权重,使用ConstructorResolver的静态内部类
// ArgumentsHolder分别对字符型和数字型的参数做权重判断,权重越小,则说明构造函数越匹配
// 对于严格模式:严格返回权重值,不会根据分别比较而返回比对值
// 注意:minTypeDiffWeight = Integer.MAX_VALUE;而权重比较返回结果都是
// 在Integer.MAX_VALUE做减法,起返回最大值为Integer.MAX_VALUE
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 根据权重获取到了最匹配的构造函数 将其赋值
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
// 如果未能明确解析出需要使用的工厂方法
// 对于具有相同参数个数的方法,如果具有相同类型的权值,则收集这些候选对象,并最终引发歧义异常。
// 但是,只在非宽松的构造函数解析模式中执行该检查,并显式地忽略覆盖的方法(具有相同的方法)。
//该行代码是在 大的条件语句factoryMethodToUse 是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);
}
}
//7、到了这里我们已经获取到了唯一一个合适进行bean实例化的构造函数
//这里会从beanFactory 获取具体的实例化策略 调用构造函数进行bean实例化
try {
final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
Object beanInstance;
if (System.getSecurityManager() != null) {
final Constructor> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged((PrivilegedAction
创建一个默认的bean实例的包装类BeanWrapperImpl实例
判断有无显式指定构造方法参数,如果有则优先使用
从缓存中尝试获取解析的构造函数方法
如果缓存中没有说明构造器函数没有被解析存储到beanDefintion的缓存中,需要解析构造器参数并判断使用哪个构造器参数
根据构造参数 来确定对应的构造函数
排序侯选者构造方法列表 优先选择公有构造方法和参数最多的构造方法
到了这里我们已经获取到了唯一一个合适进行bean实例化的构造函数
//构造函数的实例化方式
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor> ctor, @Nullable Object... args) {
//如果beanDefiontion中有相关的replace-method、lookup-method
//需要覆盖、动态替换的方法需要使用cglib进行动态代理
//这时不适用构造函数进行bean的实例化 而是使用instantiateWithMethodInjection()进行操作
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// 设置对于私有的构造方法 设置允许访问
AccessController.doPrivileged((PrivilegedAction
至此有关bean实例获取逻辑分析完毕。有不妥之处敬请指教。