基于最新Spring 5.x,详细介绍了getSingleton方法中的核心createBean方法的全部流程以及该方法内部的createBeanInstance方法的源码——bean的创建以及构造器的自动注入的过程,即bean的“实例化”。
上一篇文章:Spring IoC容器初始化源码(6)—finishBeanFactoryInitialization实例化Bean的整体流程以及某些扩展点中,我们主要讲解了ClassPathXmlApplicationContext IoC容器初始化的refresh方法中的finishBeanFactoryInitialization方法的整体流程以及部分源码解析,比如DependsOn依赖校验、FactoryBean的特殊获取模式、getSingleton获取单例实例流程,以及SmartInitializingSingleton、FactoryBean、SmartFactoryBean扩展点。
现在我们继续向下学习refresh()方法的中的finishBeanFactoryInitialization方法的内容
,接下来就是getSingleton方法中的核心createBean方法
,这个方法用于实现singleton作用域的单例对象创建,它将使用给定合并的 bean 定义和参数创建、填充 bean 实例,并且应用后处理器。本文主要讲解createBean方法的全部流程以及该方法内部的createBeanInstance方法的源码——bean的实例化以及基于构造器的自动注入。
Spring IoC容器初始化源码(1)—setConfigLocations设置容器配置信息
Spring IoC容器初始化源码(2)—prepareRefresh准备刷新、obtainFreshBeanFactory加载XML资源、解析<beans/>标签
Spring IoC容器初始化源码(3)—parseDefaultElement、parseCustomElement解析默认、扩展标签,registerBeanDefinition注册Bean定义
Spring IoC容器初始化源码(4)—<context:component-scan/>标签解析、spring.components扩展点、自定义Spring命名空间扩展点
Spring IoC容器初始化源码(5)—prepareBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors方法
Spring IoC容器初始化源码(6)—finishBeanFactoryInitialization实例化Bean的整体流程以及某些扩展点
Spring IoC容器初始化源码(7)—createBean实例化Bean的整体流程以及构造器自动注入
Spring IoC容器初始化源码(8)—populateBean、initializeBean实例化Bean以及其他依赖注入
< context:property-placeholder/>标签以及PropertySourcesPlaceholderConfigurer占位符解析器源码深度解析
三万字的ConfigurationClassPostProcessor配置类后处理器源码深度解析
基于JavaConfig的AnnotationConfigApplicationContext IoC容器初始化源码分析
createBean方法使用给定合并的 bean 定义和参数创建、填充 bean 实例,并且应用后处理器。createBean方法是真正完成bean实例创建的方法。它位于AbstractAutowireCapableBeanFactory类中,还支持依赖自动注入的功能。
/**
* AbstractAutowireCapableBeanFactory的方法,doGetBean的核心方法之一
*
* 使用给定合并的 bean 定义和参数创建、填充 bean 实例,并且应用后处理器等。支持自动注入
*
* @param beanName bean name
* @param mbd 已合并的bean定义
* @param args 用于构造器或工厂方法调用的显式参数
* @return bean的新实例
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
//根据bean定义中的属性解析class,如果此前已经解析过了那么直接返回beanClass属性指定的Class对象,否则解析className字符串为Class对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
//如果已解析的class不为null,并且beanClass属性不为null,并且beanClass属性类型不是Class类型,即存的是全路径各类名字符串
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
//使用一个新的RootBeanDefinition克隆参数中的mbd
mbdToUse = new RootBeanDefinition(mbd);
//将mbdToUse的beanClass属性设置为解析出来的resolvedClass
mbdToUse.setBeanClass(resolvedClass);
}
try {
//准备以及验证方法重写,也就是、这两个标签的配置,此前IoC学习的时候已经给介绍过了,一般用的不多
//主要是校验指定名称的方法是否存在,如果不存在则抛出异常;以及设置是否存在重载方法,如果不存在重载方法,那么后续不需要参数校验。
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
//Spring实例化bean之前的处理,给InstantiationAwareBeanPostProcessor后处理器一个返回代理对象来代替目标bean实例的机会
//一般用不到,都是走Spring创建对象的逻辑
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//如果bean不为null,那么就返回这个代理bean
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//调用doCreateBean方法真正的创建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);
}
}
prepareMethodOverrides方法用于准备以及验证方法重写,也就是、< replaced-method/>这两个标签的配置,此前IoC学习的时候已经给介绍过了,一般用的不多。主要是校验指定名称的方法是否存在,如果不存在则抛出异常,以及设置是否存在重载方法,如果不存在重载方法,那么后续不需要参数校验。
< lookup-method/>、< replaced-method/>这两个标签使用同一个配置属性,即位于AbstractBeanDefinition中的methodOverrides中。
/**
* AbstractBeanDefinition的属性
* 、 这两个标签的配置的方法
*
*/
private MethodOverrides methodOverrides = new MethodOverrides();
/**
* AbstractBeanDefinition的方法
*
* 验证并准备为此 bean 定义的方法重写。检查是否存在具有指定名称的方法。
*/
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
//检查是否存在查找方法并确定其重载状态
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
/**
* AbstractBeanDefinition的方法
*
* 如果已为此 bean 定义了方法覆盖,则返回true
*/
public boolean hasMethodOverrides() {
return !this.methodOverrides.isEmpty();
}
/**
* AbstractBeanDefinition的方法
*
* 返回有关要由 IoC 容器重写的方法的信息。如果没有方法重写,将返回空集合。永远不会返回null
*/
public MethodOverrides getMethodOverrides() {
return this.methodOverrides;
}
/**
* AbstractBeanDefinition的方法
*
* 验证并准备给定的方法重写。
* 检查具有指定名称的方法是否存在,以及如果找到一个同名方法,则将该方法标记为未重载来避免参数检查的开销。
*
* @param mo 要验证的MethodOverride对象
*/
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
//在当前Class中获取具有给定方法名的方法的数量
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
//如果数量为0,那么抛出异常
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
//如果数量为0,那么将当前MethodOverride对象的overloaded属性设置为false
//表示不存在重载方法,用来避免后续的参数类型检查的开销
else if (count == 1) {
mo.setOverloaded(false);
}
}
resolveBeforeInstantiation方法用在Spring实例化bean之前,给InstantiationAwareBeanPostProcessor后处理器一个返回代理对象来代替目标bean实例的机会。
该方法中会尝试调用InstantiationAwareBeanPostProcessor类型的后处理器(如果存在)的postProcessBeforeInstantiation方法,如果该方法不返回null,那么表示使用了后处理器的方法来创建bean实例,后续将同样会调用全部后处理器的postProcessAfterInitialization方法,但是没有使用Spring的逻辑来创建bean实例。
记住,resolveBeforeInstantiation方法是在Spring创建bean实例之前调用的,如果该方法返回值不为null,则直接返回该值,表示使用后处理器的方法实例化了bean,后续不会走Spring实例化bean的逻辑。如果返回null,则继续走Spring的逻辑。但是一般都是返回null的。
InstantiationAwareBeanPostProcessor后处理器接口继承并扩展了BeanPostProcessor接口,新增了postProcessBeforeInstantiation、postProcessAfterInstantiation、postProcessPropertyValues回调方法,这些回调方法同样用于在创建bean实例的某个时刻进行回调,比如这个地方就会回调postProcessBeforeInstantiation方法。
/**
* AbstractAutowireCapableBeanFactory的方法
*
* 在Spring的bean实例化之前使用后处理器来实例化bean,这是一种快速实例化bean的方法
*
* @param beanName beanName
* @param mbd bean定义
* @return 快速实例化的 bean 实例,如果没有,则为null
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//判断初始化之前有没有处理,有的话直接返回null
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 确保mbd不是合成的,并且具有InstantiationAwareBeanPostProcessor这个后处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//获取这个bean的目标class
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//应用InstantiationAwareBeanPostProcessor后处理器的postProcessBeforeInstantiation方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
//如果bean不为null
if (bean != null) {
//那么继续应用所有已注册的后处理器的postProcessAfterInitialization方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
//如果bean不为空,则将RootBeanDefinition的beforeInstantiationResolved属性赋值为true,表示在Spring实例化之前已经解析
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
/**
* AbstractBeanFactory的属性
*
* 指示是否注册了任何InstantiationAwareBeanPostProcessor后处理器
*/
private volatile boolean hasInstantiationAwareBeanPostProcessors;
/**
* AbstractBeanFactory的方法
*
* 返回此工厂是否持有InstantiationAwareBeanPostProcessor处理器,该处理器将在创建时应用于单例bean
* 这个属性是在registerBeanPostProcessors方法中设置的,此前已经介绍过了,在这里终于用上了这个属性
*/
protected boolean hasInstantiationAwareBeanPostProcessors() {
return this.hasInstantiationAwareBeanPostProcessors;
}
/**
* AbstractAutowireCapableBeanFactory的方法
*
* Spring实例化bean之前应用InstantiationAwareBeanPostProcessors后处理器的postProcessBeforeInstantiation方法
*
* @param beanClass 要实例化的bean的Class
* @param beanName beanName
* @return 要使用的代理 bean 对象,或null
*/
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
//遍历全部bean后处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//找到类型为InstantiationAwareBeanPostProcessor的后处理器进行回调
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//回调
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
//如果结果不为null,表示创建了代理对象,那么直接返回该对象
if (result != null) {
return result;
}
}
}
return null;
}
/**
1. bean实例化之后应用所有已注册的BeanPostProcessor后处理器的postProcessBeforeInstantiation方法
2. 3. @param existingBean 现有的 bean 实例
3. @param beanName beanName
4. @return 要使用的 bean 实例,无论是原始实例还是包装实例
*/
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
//用来保存返回的结果,默认为传递的existingBean
Object result = existingBean;
//遍历全部已注册的BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//按照遍历顺序调用postProcessAfterInitialization方法
Object current = processor.postProcessAfterInitialization(result, beanName);
//如果当前BeanPostProcessor后处理器的返回值为null,那么返回上一个不为null的结果
if (current == null) {
return result;
}
//更新要返回的结果
result = current;
}
//遍历、处理完毕,返回最终的结果
return result;
}
以do开头的方法,真正的Spring创建bean实例的核心方法,将会对进行实例化和初始化,并且处理循环依赖。大概步骤为:
createBeanInstance
方法使用适当的实例化策略(Supplier、工厂方法、有参构造器自动注入、无参构造器)创建Bean实例,并返回包装类BeanWrapper。applyMergedBeanDefinitionPostProcessors
,应用MergedBeanDefinitionPostProcessor类型后处理器的postProcessMergedBeanDefinition方法。被用来查找、解析各种注解,比如@PostConstruct、@PreDestroy回调注解,@WebServiceRef、@EJB、@Resource资源注解,@Autowired、@Value、@Inject自动注入注解。设置earlySingletonExposure变量为true
,表示允许早期单例对象暴露,可被用于创建代理对象,进而变更早期单例对象实例。如果earlySingletonExposure==true,即允许早期单例对象暴露,那么创建一个ObjectFactory的lambda对象通过addSingletonFactory方法存入singletonFactories缓存中,用于解决setter方法和注解反射注入的单例bean循环依赖以及AOP代理对象的创建的问题
。populateBean
,填充(装配)通过createBeanInstance创建的bean实例,也就是XML或者注解的基于setter方法和字段反射进行属性注入过程。initializeBean
,继续初始化bean实例,也就是回调各种方法,比如顺序回调所有设置的init初始化方法,以及回调Aware接口的方法,进行AOP代理等操作。如果
earlySingletonExposure==true,即允许早期单例对象暴露,那么进行循环依赖检查,看是否需要抛出异常。
通过getSingleton(beanName, false)尝试从缓存中获取当前bean实例。实际上就是此前通过addSingletonFactory存入进singletonFactories缓存中了一个ObjectFactory的lambda对象。
这里的allowEarlyReference参数为false,即不允许获取早期引用,因此只会尝试从singletonObjects和earlySingletonObjects这两个缓存中获取bean实例earlySingletonReference,没找到就返回null。如果当前beanName不是手动注册的或者没有循环依赖,那么应该为null。
如果获取的earlySingletonReference不为null,说明存在循环依赖,并且此前已经被调用了ObjectFactory的getObject方法,也就是getEarlyBeanReference。getEarlyBeanReference方法中,会回调所有SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法,因此将可能进行基于AbstractAutoProxyCreator的Spring AOP代理增强,比如自定义Spring AOP代理、Spring声明式事务等,这里获取的earlySingletonReference可能就是一个代理对象。
如果在经过populateBean和initializeBean之后返回的对象exposedObject还是等于原始对象bean(比较的地址值,即是否是同一个对象),即说明当前循环依赖的bean实例没有在populateBean和initializeBean这两个方法中调用的回调方法中被代理增强,或者只有基于AbstractAutoProxyCreator的Spring AOP代理增强,但是这在getEarlyBeanReference方法中已经被增强,Spring会保证基于AbstractAutoProxyCreator的增强只会进行一次,那么经过这两个填方法之后将仍然返回原始的bean。
那么exposedObject赋值为earlySingletonReference,对之前的循环引用没影响,这里的earlySingletonReference可能就是被基于AbstractAutoProxyCreator代理增强的代理对象。
如果不相等,则说明被代理过,比如还有Spring @Async异步任务的AOP增强,由于它是通过AbstractAdvisingBeanPostProcessor来实现的,因此,经过这两个方法之后将返回一个新的代理的bean,这样exposedObject就和原来的bean不相等了。
这里的earlySingletonReference可能就是被基于AbstractAutoProxyCreator代理增强的代理对象,但是这里的exposedObject可能又是被基于AbstractAdvisingBeanPostProcessor代理增强的代理对象,那是肯定不行的,因此将会检测循环依赖并抛出异常。
如果此前有其他的依赖当前bean的bean被创建(对应的beanName存在于alreadyCreated缓存集合中),可能会导致其他bean中注入的实例并不是真正最终需要注入的代理对象,那么将会抛出BeanCurrentlyInCreationException异常,比如@Async异步任务的循环依赖,此时可以使用@Lazy解决。
registerDisposableBeanIfNecessary
方法,尝试将当前bean实例注册为可销毁的bean,即存入disposableBeans缓存中,后续容器销毁时将会进行销毁回调。注册销毁的回调方法,可以来自于@PreDestroy注解、XML配置的destroy-method方法,以及DisposableBean接口,甚至AutoCloseable接口。我们主要就是解析内部的createBeanInstance、applyMergedBeanDefinitionPostProcessors、populateBean、initializeBean、registerDisposableBeanIfNecessary这几个方法,更多详情见代码注释!
/**
* 未完成的工厂Bean实例的缓存:工厂Bean的名称 到 BeanWrapper
*/
private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();
/**
* AbstractAutowireCapableBeanFactory的方法
*
* 实际上创建指定的 bean实例的方法。此时已完成预创建处理,比如postProcessBeforeInstantiation回调。
* 支持使用默认构造器、使用工厂方法和自动注入带参构造器实例化bean。
* 回调所有配置的initMethod方法
*
* @param beanName beanName
* @param mbd 已合并bean定义
* @param args 用于构造器或工厂方法调用的显式参数
* @return bean的新实例
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
/*
* 实例化bean
*/
//instanceWrapper表示一个bean的包装类对象
BeanWrapper instanceWrapper = null;
//如果mbd是单例的
if (mbd.isSingleton()) {
//尝试直接从factoryBeanInstanceCache中移除并获取正在创建中的FactoryBean的指定beanName的BeanWrapper
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//如instanceWrapper果为null,一般都是走这个逻辑
if (instanceWrapper == null) {
/*
* 1 核心方法之一,使用适当的实例化策略创建Bean实例,并返回包装类BeanWrapper:
* 1 根据生产者Supplier实例化bean
* 2 根据工厂方法实例化bean
* 3 如果可以自动注入,则使用构造器自动注入实例化bean
* 4 不能自动注入,则使用默认无参构造器实例化bean
*
* 该方法结束,已经实例化bean完毕(可能进行了构造器依赖注入),后续就是其他依赖注入(setter方法、注解反射)的过程
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//返回包装的bean 实例
Object bean = instanceWrapper.getWrappedInstance();
//返回包装的 bean 实例的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
//resolvedTargetType缓存设置为beanType
mbd.resolvedTargetType = beanType;
}
synchronized (mbd.postProcessingLock) {
//如果没有应用过MergedBeanDefinitionPostProcessor
if (!mbd.postProcessed) {
try {
/*
* 2 核心方法之二
* 应用MergedBeanDefinitionPostProcessor类型后处理器的postProcessMergedBeanDefinition方法,允许后处理器修改已合并的 bean 定义
* 最重要的是它被用来查找、解析各种注解,常见的MergedBeanDefinitionPostProcessor的实现以及对应postProcessMergedBeanDefinition方法的功能有:
* 1 InitDestroyAnnotationBeanPostProcessor -> 处理方法上的@PostConstruct、@PreDestroy注解,用于初始化、销毁方法回调
* 2 CommonAnnotationBeanPostProcessor -> 处理字段和方法上的@WebServiceRef、@EJB、@Resource注解,用于资源注入
* 3 AutowiredAnnotationBeanPostProcessor -> -> 处理字段和方法上的@Autowired、@Value、@Inject注解,用于自动注入
* 4 ApplicationListenerDetector -> 记录ApplicationListener类型的bean是否是单例的,后面监听器过滤的时候才会用到(不必关心)
*
* 这一步仅仅是查找、简单解析Class中的各种注解,并缓存起来,后面时机到了,自然会调用这些被缓存的注解,完成它们的功能
*/
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
//标志位改为true
mbd.postProcessed = true;
}
}
/*
* 3 解决setter方法和注解反射注入的单例bean循环依赖问题
*/
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//如果当前bean的"singleton"单例,并且允许循环依赖(默认允许),并且正在创建当前单例bean实例
//那么earlySingletonExposure设置为ture,表示允许早期单例实例的暴露,用于解决循环依赖
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:
* 将早期单例实例工厂存入singletonFactories缓存中,用于解决循环依赖
* 如果A依赖B、B依赖A,那么注入的时候,将会注入一个从singletonFactories中的ObjectFactory获取的早期对象
* 为什么叫"早期"呢?因为此时该实例虽然被创建,但是可能还没有执行后续的依赖注入(setter方法、注解反射)的过程,该bean实例是不完整的
* 但是此时能够保证获取的依赖不为null而不会抛出异常,并且和后续进行的注入对象是同一个对象,从而在不知不觉中解决循环依赖
*
* 以前的版本第二个参数传递的是一个ObjectFactory的匿名对象,Spring5以及Java8的之后第二个参数传递的是一个lambda对象
* lambda语法更加简单,采用invokedynamic指令运行时动态构建类,不会生成额外的class文件
*
* 这个lambda的意思就是,ObjectFactory对象的getObject方法实际上就是调用这里的getEarlyBeanReference方法
*
* getEarlyBeanReference:
* 应用SmartInstantiationAwareBeanPostProcessor后处理器的getEarlyBeanReference方法
* 该方法可以改变要返回的提前暴露的单例bean引用对象,默认都是返回原值的,即不做改变,但是我们可以自己扩展。但是如果存在Spring AOP,则该方法可能会创建代理对象。
*/
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
/*
* 4 初始化 bean 实例
* 前面的createBeanInstance操作被称为"实例化"bean操作,简单的说就调用构造器创建对象
* 下面的操作就是"初始化"bean的操作,简单的说就是对bean实例进行依赖注入以及各种回调
*/
Object exposedObject = bean;
try {
/*
* 核心方法之四 populateBean
*
* 填充(装配)bean实例,也就是setter方法和注解反射的属性注入过程
* 这里又有可能由于依赖其他bean而导致其他bean的初始化
*/
populateBean(beanName, mbd, instanceWrapper);
/*
* 核心方法之五 initializeBean
* 继续初始化bean实例,也就是回调各种方法
* 比如顺序回调所有设置的init初始化方法,以及回调Aware接口的方法,进行AOP代理等操作。
*/
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);
}
}
/*
* 5 循环依赖检查,看是否需要抛出异常
*/
//如果允许暴露早期单例实例
if (earlySingletonExposure) {
/*
* 获取当前单例实例缓存,allowEarlyReference参数为false,因此只会尝试从singletonObjects和earlySingletonObjects中查找,没找到就返回null
*
* 如果不为null,说明存在循环依赖,此前另一个互相依赖的Bean通过getSingleton(beanName)获取当前bean实例时,
* 获取的结果就是ObjectFactory#getObject的返回值,实际上就是getEarlyBeanReference方法返回的结果,因此
* 最后还会将结果存入earlySingletonObjects缓存,因此这里获取的实际上就是另一个Bean注入的实例,可能是一个代理对象
*/
Object earlySingletonReference = getSingleton(beanName, false);
/*
* 如果earlySingletonReference不为null,说明存在循环依赖,并且此前已经调用了ObjectFactory#getObject方法,即getEarlyBeanReference方法。
* getEarlyBeanReference方法中,会回调所有SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法
* 因此将可能进行基于AbstractAutoProxyCreator的Spring AOP代理增强,比如自定义Spring AOP代理、Spring声明式事务等
*
* 这里获取的earlySingletonReference可能就是一个代理对象
*/
if (earlySingletonReference != null) {
/*
* 如果在经过populateBean和initializeBean方法之后返回的对象exposedObject还是等于原始对象bean,
* 即说明当前循环依赖的bean实例没有在populateBean和initializeBean这两个方法中调用的回调方法中被代理增强
* 或者只有基于AbstractAutoProxyCreator的Spring AOP代理增强,但是这在getEarlyBeanReference方法中已经被增强了
* Spring会保证基于AbstractAutoProxyCreator的增强只会进行一次,那么经过这两个填方法之后将仍然返回原始的bean
*
* 但是如果还有Spring @Async异步任务的AOP增强,由于它是通过AbstractAdvisingBeanPostProcessor来实现的,因此
* 经过这两个方法之后将返回一个新的代理的bean,这样exposedObject就和原来的bean不相等了
*/
if (exposedObject == bean) {
//那么exposedObject赋值为earlySingletonReference,对之前的循环引用没影响
//这里的earlySingletonReference可能就是被基于AbstractAutoProxyCreator代理增强的代理对象
exposedObject = earlySingletonReference;
}
//否则,说明该bean实例进行了其他的代理,比如Spring @Async异步任务
//继续判断如果不允许注入原始bean实例,并且该beanName被其他bean依赖
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
//获取依赖该bean的beanName数组
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
//遍历数组
for (String dependentBean : dependentBeans) {
/*
* 尝试将dependentBean对应的仅用于类型检查的已创建实例移除,如果是真正的创建的实例则不会一会,最后还会抛出异常
*
* 如果alreadyCreated缓存集合中不包含对应的dependentBean,说明该bean实例还未被真正创建,但是可能因为类型检查而创建
* 那么尝试移除对象缓存中的beanName对应的缓存(无论是否真正的因为类型检查而创建了),并返回true
* 如果alreadyCreated中包含对应的dependentBean否则,说明该bean实例因为其他用途已被创建了或者正在创建(比如真正的初始化该bean实例),
* 那么返回false,表示依赖该bean的bean实例可能已被创建了,但是注入的对象可能并不是最终的代理对象
* 因此后续将会抛出BeanCurrentlyInCreationException异常
*
* 在前面的doGetBean方法中,如果不是为了类型检查,那么会将即将获取的实例beanName通过markBeanAsCreated方法存入alreadyCreated缓存集合中
*/
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
//移除失败的dependentBean加入actualDependentBeans集合中
actualDependentBeans.add(dependentBean);
}
}
/*
* 如果actualDependentBeans集合不为空,那么表示可能有其他依赖该bean的实例注入的并不是目前最终的bean实例,那么将抛出异常。
*
* 实际上对于普通bean以及通用的AOP循环依赖注入以及事务循环依赖,Spring都可以帮我们解决循环依赖而不会抛出异常!
* 如果对@Async注解标注的类进行setter方法和反射字段注解的循环依赖注入(包括自己注入自己),就会抛出该异常。
* 而@Async类抛出异常的根本原因这个AOP代理对象不是使用通用的AbstractAutoProxyCreator的方法创建的,
* 而是使用AsyncAnnotationBeanPostProcessor后处理器来创建的,可以加一个@Lazy注解解决!
*/
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
/*
* 6 尝试将当前bean实例注册为可销毁的bean,即存入disposableBeans缓存中,后续容器销毁时将会进行销毁回调
* 注册销毁回调方法,可以来自于@PreDestroy注解、XML配置的destroy-method方法,以及DisposableBean接口,甚至AutoCloseable接口
*/
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
//返回exposedObject,该实例被创建完毕
return exposedObject;
}
/**
* AbstractBeanFactory的方法
*
* 删除给定bean名称的用于类型检查而不是真正的被创建的bean的单例实例(如果有的话)
*
* @param beanName beanName
* @return 如果beanName对应的bean已被真正的创建,否则返回false,否则返回true,表示已尝试移除
*/
protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
//如果alreadyCreated中不包含对应的dependentBean,说明该bean实例还未被真正创建
//即使被创建了,也是因为类型检查而创建的
if (!this.alreadyCreated.contains(beanName)) {
//尝试移除对象缓存中的beanName对应的缓存(无论缓存中是否真正的存在)
removeSingleton(beanName);
//返回true
return true;
}
//否则,说明该bean实例已被真正的创建了或者正在创建,那么返回false
else {
return false;
}
}
createBeanInstance是doCreateBean中的核心方法之一,将会使用使用适当的实例化策略创建Bean实例,并返回包装类BeanWrapper。采用的策略有:工厂方法实例化、自动注入带参数构造器实例化或默认无参构造器简单实例化。
/**
* AbstractAutowireCapableBeanFactory的方法
*
* 使用适当的实例化策略为指定的 bean 创建新实例
* 采用的策略有:工厂方法实例化、自动注入带参数构造器实例化或默认无参构造器简单实例化。
*
* @param beanName beanName
* @param mbd bean定义
* @param args 用于构造器或工厂方法调用的显式参数
* @return 一个新实例的 Beanwrapper对象
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
/*
* 根据bean定义中的属性解析class,如果此前已经解析过了那么直接返回beanClass属性指定的Class对象,否则解析className字符串为Class对象
*/
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//如果beanClass不为null,并且该类的访问权限修饰符不是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());
}
//获取用于创建 bean 实例的回调生产者。这是Spring5以及Java8的新特性
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
/*
* 1 如果存在bean实例生产者
*/
if (instanceSupplier != null) {
//那么从给定的生产者获取 bean 实例
return obtainFromSupplier(instanceSupplier, beanName);
}
/*
* 2 如果存在工厂方法,即XML的factory-method属性
*/
if (mbd.getFactoryMethodName() != null) {
//那么从工厂方法中获取 bean 实例
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
/*
* 3 Spring会将此前已经解析、确定好的构造器缓存到resolvedConstructorOrFactoryMethod中
* 后续再次创建对象时首先尝试从缓存中查找已经解析过的构造器或者工厂方法,避免再次创建相同bean时再次解析
*
* 对于原型(prototype)bean的创建来说,这非常的有用,可以快速的创建对象,称为Shortcut
*/
//resolved表示是否已解析构造器或者工厂方法的标志,默认false
boolean resolved = false;
//resolved表示是否构造器自动注入的标志,默认false
boolean autowireNecessary = false;
//如果没有指定外部参数
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//如果解析的构造器或工厂方法缓存不为null,表示已经解析过
if (mbd.resolvedConstructorOrFactoryMethod != null) {
//resolved标志位设置为true
resolved = true;
//autowireNecessary标志位设置为constructorArgumentsResolved
//constructorArgumentsResolved属性表示是否已经解析了构造器参数,如果已经解析了,则需要通过缓存的构造器来实例化
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已经解析过,则使用解析过的构造器进行初始化,设置的显示参数此时无效
if (resolved) {
//如果支持自动注入
if (autowireNecessary) {
//使用构造器自动注入初始化
return autowireConstructor(beanName, mbd, null, null);
} else {
//使用默认无参构造器初始化
return instantiateBean(beanName, mbd);
}
}
/*
* 4 一般bean第一次解析都是走下面的逻辑,使用构造器初始化
*/
/*
* 利用SmartInstantiationAwareBeanPostProcessor后处理器回调,自动匹配、推测需要使用的候选构造器数组ctors
* 这里的是解析注解,比如@Autowired注解,因此需要开启注解支持
*/
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
/*
* 5 如果ctors的候选构造器数组不为null(这是查找注解,比如@Autowired注解),
* 或者自动注入模式为构造器自动注入(这是XML设置的自动注入模式)
* 或者XML定义了 标签,或者外部设置的参数args不为空。
*
* 四个条件满足一个,那么使用构造器自动注入
*/
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//那么使用构造器自动注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
/*
* 6 没有特殊处理,使用默认无参构造器初始化。
* 在大量使用注解的今天,一般都是通过无参构造器创建对象的,还能避免构造器的循环依赖
* 当然无参构造器一般也是在上面的autowireConstructor方法中调用的
*/
return instantiateBean(beanName, mbd);
}
从给定的Supplier生产者获取 bean 实例。Spring5新增的方法。该方法的优先级最高,我们可以通过setInstanceSupplier方法设置自己的生产者,比如可以通过postProcessBeanFactory回调方法修改bean定义,用的比较少。
/**
* 当前创建的 bean 的名称,用于从用户指定的供应商回调触发的 getBean 等调用上的隐式依赖项注册
* 支持obtainFromSupplier方法加入的属性
*/
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
/**
* AbstractAutowireCapableBeanFactory的方法
*
* 从给定的生产者获取 bean 实例。
*
* @param instanceSupplier 配置的bean实例生产者
* @param beanName 相应的beanName
* @return 一个新实例的 Beanwrapper对象
*/
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
//获取当前线程正在创建的 bean 的名称支持obtainFromSupplier方法加入的属性
String outerBean = this.currentlyCreatedBean.get();
//设置为给定的beanName,表示正在创建当前beanName的实例
this.currentlyCreatedBean.set(beanName);
try {
//从生产者获取实例
instance = instanceSupplier.get();
} finally {
//如果outerBean不为null
if (outerBean != null) {
//那么还是设置为outerBean,表示正在创建outerBean的实例
this.currentlyCreatedBean.set(outerBean);
}
//否则,移除当前currentlyCreatedBean的key,表示没有使用Supplier创建
else {
this.currentlyCreatedBean.remove();
}
}
//如果生产者返回null,那么返回NullBean包装bean
if (instance == null) {
instance = new NullBean();
}
//新建BeanWrapperImpl
BeanWrapper bw = new BeanWrapperImpl(instance);
//初始化BeanWrapper
initBeanWrapper(bw);
//返回BeanWrapper
return bw;
}
通过检查所有已注册的SmartInstantiationAwareBeanPostProcessor后处理器,确定要用于给定 bean 的候选构造器。
注意这里是检查注解,比如@Autowired、@Inject注解,因此需要开启注解支持,比如< annotation-config/>或者< component-scan/>标签。具体的检查逻辑是在SmartInstantiationAwareBeanPostProcessor后处理器的determineCandidateConstructors方法中执行的,所以说这个determineCandidateConstructors回调方法是在对象实例化之前执行的!
/**
* 通过检查所有已注册的SmartInstantiationAwareBeanPostProcessor后处理器,确定要用于给定 bean 的候选构造器
* 具体的检查逻辑是在SmartInstantiationAwareBeanPostProcessor后处理器的determineCandidateConstructors方法中
*
* 注意这里是检查注解,比如@Autowired注解,因此需要开启注解支持,比如annotation-config或者component-scan
* 该类型的后置处理器的实现有两个:ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor,AutowiredAnnotationBeanPostProcessor
* ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor中什么也没干,因此具体的逻辑都在AutowiredAnnotationBeanPostProcessor中
*
* 所以说这个后置处理器的determineCandidateConstructors方法执行时机是在: 对象实例化之前执行
*
* @param beanClass beanClass
* @param beanName beanName
* @return 候选构造器数组,如果没有指定则为null
*/
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
//如果beanClass不为null,并且具有InstantiationAwareBeanPostProcessor这个类型的后处理器
//SmartInstantiationAwareBeanPostProcessor继承了InstantiationAwareBeanPostProcessor
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
//遍历所有注册的BeanPostProcessor后处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果属于SmartInstantiationAwareBeanPostProcessor类型
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
//强制转型
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//回调determineCandidateConstructors方法,返回候选构造器数组
//比如使用@Autowired注解标注的构造器都被当作候选构造器,加入到数组中,留待后续继续筛选
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
//如果返回值不为null,那么直接返回结果,表明解析到了候选构造器
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
determineCandidateConstructors用于确定给定 bean 的候选构造器,返回找到的候选构造器数组。
SmartInstantiationAwareBeanPostProcessor类型的后置处理器具有一个重要的抽象实现InstantiationAwareBeanPostProcessorAdapter,而它的具体实现有大概两个,一个是ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor和AutowiredAnnotationBeanPostProcessor,它们都是继承了InstantiationAwareBeanPostProcessorAdapter。
前面讲过,Spring在解析< component-scan/>标签的时候,在registerAnnotationConfigProcessors方法中会注册一些后置处理器,其中就有ConfigurationClassPostProcessor 和AutowiredAnnotationBeanPostProcessor,这也是使用这两个标签就能开启注解支持的原理。
其在InstantiationAwareBeanPostProcessorAdapter中的默认实现返回null。
/**
* InstantiationAwareBeanPostProcessorAdapter抽象类中的默认实现
*
* 确定要用于给定 bean 的候选构造器。默认实现返回null
* @param beanClass bean 的原始Class,永远不为null
* @param beanName beanName
* @return 候选构造器数组,如果没有找到就返回null
* @throws org.springframework.beans.BeansException in case of errors
*/
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
实际上,ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor实现类重写该方法, 而AutowiredAnnotationBeanPostProcessor则重写了该方法,这也是我们主要关心的方法。
AutowiredAnnotationBeanPostProcessor重写的determineCandidateConstructors方法同样用于查找候选构造器,不过还能解析带有自动注入注解(@Autowired、@Inject)的构造器,如果返回的候选构造器数组不为null,那么后续将会调用autowireConstructor使用构造器自动装配模式初始化实例!
最重要的是我们应该知道AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors方法的查找规则:
我们在IoC学习的部分就介绍了@Autowired的注解以及标注在构造器上时的解析规则,而现在,这里的代码实际上就是IoC中通过注解比如@Autowired、@Inject来确定候选构造器的真正源码和完整的规则,可以发现和在学习时通过“经验猜测”总结的规则还是有些出入的,这就是阅读源码的好处。
请注意,这里仅仅是筛选出候选构造器数组,里面可能会有多个候选构造器,因此后面还会尝试筛选出一个最合适的构造器进行最终创建bean实例的操作。
/**
* 查找方法检查的缓存
*/
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
/**
* 找到的候选构造器缓存
*/
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
/**
* AutowiredAnnotationBeanPostProcessor重写的方法
*
* 解析@Autowired、@Value、@Inject注解,确定要用于给定 bean 的候选构造器。
* 该方法仅被AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors方法调用
*
* @param beanClass bean 的Class,永远不为null
* @param beanName beanName
* @return 候选构造器数组,如果没有站到就返回null
*/
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
/*
* 1 检查查找方法注入,即@Lookup注解,用于原型bean的获取,很少用到
* 这部分代码不必关心
*/
if (!this.lookupMethodsChecked.contains(beanName)) {
//确定给定类是否是承载指定注释的候选项(在类型、方法或字段级别)。
//如果任何一个注解的全路径名都不是以"java."开始,并且该Class全路径名以"start."开始,或者Class的类型为Ordered.class,那么返回false,否则其他情况都返回true
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {
/*
* 循环过滤所有的方法(不包括构造器)
*/
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//尝试获取方法上的@Lookup注解
Lookup lookup = method.getAnnotation(Lookup.class);
//如果存在@Lookup注解
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
//创建一个LookupOverride对象存入当前beanName的mbd中
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
//加入methodOverrides内部的overrides集合中
mbd.getMethodOverrides().addOverride(override);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
});
//获取父类Class
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
}
//检查过的beanName加入到lookupMethodsChecked中,无论有没有@Lookup注解
this.lookupMethodsChecked.add(beanName);
}
/*
* 2 查找候选构造器
*/
//首先快速检查缓存,看是否已经存在指定类型的候选构造器依赖缓存,即此前是否已解析过
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
/*
* 如果缓存为null,说明没解析过,那么需要解析
* 解析之后会将该类型Class以及对应的结果加入candidateConstructorsCache缓存,后续同类型再来时不会再次解析
*/
if (candidateConstructors == null) {
// 加锁防止并发
synchronized (this.candidateConstructorsCache) {
//加锁情况下再次获取该类型的缓存
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
/*
* 如果缓存为null,说明没解析过,那么需要解析
* 如果不为null,那么这一段逻辑就跳过了
*/
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
//反射获取当前类型的全部构造器数组
rawCandidates = beanClass.getDeclaredConstructors();
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
//candidates用于保存满足条件的候选构造器(存在@Inject注解或者@Autowired注解)
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
//必须的构造器(存在@Inject注解,或者存在@Autowired注解并且required属性为true)
Constructor<?> requiredConstructor = null;
//默认的构造器(无参构造器)
Constructor<?> defaultConstructor = null;
//Kotlin专用,Java用不上
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
/*
* 循环全部构造器进行解析
*/
for (Constructor<?> candidate : rawCandidates) {
//如果不是合成构造函数,一般都不是
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
} else if (primaryConstructor != null) {
continue;
}
//获取构造器上的自动注入注解的MergedAnnotation,一般是按顺序查找@Autowired、@Value、@Inject注解,找到某一个就返回
//@Value注解不能标注在构造器上,@Inject很少使用,因此构造器大部分都返回@Autowired的MergedAnnotation(如果标注了@Autowired注解)
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
//如果不存在@Autowired、@Inject注解
if (ann == null) {
//返回给定类的用户定义的类:通常只是给定类即返回原始类,但在 CGLIB 生成的子类的情况下返回原始类。
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//如果确实是CGLIB子类,那么解析原始类,看原始类上面有没有自动注入的注解
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
} catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
/*
* 如果存在@Autowired或者@Inject自动注入注解
*/
if (ann != null) {
//如果requiredConstructor不为null,这是不允许的,抛出异常
//如果存在使用了@Autowired(required = true)或者@Inject注解的构造器,那么就不允许其他构造器上出现任何的自动注入注解
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//判断是否是@Inject注解,或者是@Autowired注解并且required属性为true,即判断是否是必须的构造器
boolean required = determineRequiredStatus(ann);
//如果是必须的构造器
if (required) {
//如果candidates不为空,那么同样抛出异常
//这说明如果存在@Autowired(required = true)或者@Inject注解,那么只能在一个构造器上,且其他构造器上不能出现自动注入注解
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
//那么requiredConstructor等于candidate,即使用了@Autowired(required = true)或者@Inject注解的构造器
requiredConstructor = candidate;
}
//只要存在@Autowired或者@Inject自动注入注解,就会被加入candidates集合
candidates.add(candidate);
}
/*
* 否则,表示还是不存在@Autowired或者@Inject自动注入注解
*
* 判断当前构造器是否是无参构造器,如果是,那么默认构造器就是无参构造器
*/
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
/*
* 获取最终的candidateConstructors,即候选构造器数组
*/
/*
* 如果candidates不为空,说明存在具有@Autowired或者@Inject注解的构造器
*/
if (!candidates.isEmpty()) {
//如果requiredConstructor为null,即全部都是@Autowired(required = false)的注解
if (requiredConstructor == null) {
//如果defaultConstructor不为null,即存在无参构造器
if (defaultConstructor != null) {
//那么candidates还要加上无参构造器
candidates.add(defaultConstructor);
}
//否则,如果candidates只有一个元素,即只有一个构造器,那么输出日志
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
//candidates转换为数组,赋给candidateConstructors
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
/*
* 否则,如果只有一个构造器,并且构造器参数大于0
*/
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
//新建长度为1的数组,加入该构造器,赋给candidateConstructors
candidateConstructors = new Constructor<?>[]{rawCandidates[0]};
}
//否则,Kotlin专用,不必关心
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[]{primaryConstructor, defaultConstructor};
}
//否则,Kotlin专用
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[]{primaryConstructor};
}
//否则,新建空的数组,加入该构造器,赋给candidateConstructors
else {
candidateConstructors = new Constructor<?>[0];
}
/*
* 将对该类型Class及其解析之后的candidateConstructors,存入candidateConstructorsCache缓存,value一定不为null
* 后续同类型的Class再来时,不会再次解析
*/
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//如果缓存不为null则直接到这一步,或者解析了构造器之后,也会到这一步
//如果candidateConstructors没有数据,就返回null
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
findAutowiredAnnotation方法是通用方法,用于查找构造器、方法、字段上的自动注入注解。
在AutowiredAnnotationBeanPostProcessor初始化的时候,一般的自动注入注解的类型@Autowired、@Value、@Inject(必须有JSR-330的API)就按照顺序被加入到AutowiredAnnotationBeanPostProcessor内部的autowiredAnnotationTypes缓存中了。
这里的查找是按照顺序查找,只要找到一个自动注入注解就返回,类似于“短路法”。因此注解解析的优先级:@Autowired > @Value > @Inject。@Value注解不能标注在构造器上(但是可以标注在字段、方法、参数方法),@Inject很少使用,因此构造器大部分都返回@Autowired的MergedAnnotation(如果标注了@Autowired注解)。
/**
* AutowiredAnnotationBeanPostProcessor的属性
* 存储自动注入的类型
*/
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
/**
* AutowiredAnnotationBeanPostProcessor的方法
*
* 获取构造器、方法、字段上的@Autowired、@Value、@Inject注解的MergedAnnotation
* 按照顺序查找,因此优先级@Autowired > @Value > @Inject
*
* @param ao 指定元素,可能是构造器、方法、字段
* @return @Autowired、@Value、@Inject注解的MergedAnnotation,没有就返回null
*/
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
//创建一个新的MergedAnnotations实例,其中包含指定元素中的所有注解和元注解
MergedAnnotations annotations = MergedAnnotations.from(ao);
//遍历是否存在autowiredAnnotationTypes中的类型的注解:按照顺序为@Autowired、@Value、@Inject
//autowiredAnnotationTypes中的元素在AutowiredAnnotationBeanPostProcessor初始化时就添加进去了
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
//尝试获取该类型的注解
MergedAnnotation<?> annotation = annotations.get(type);
//如果存在,那么直接返回该注解的MergedAnnotation
if (annotation.isPresent()) {
return annotation;
}
}
//返回null
return null;
}
/**
* AutowiredAnnotationBeanPostProcessor的构造器
*
* 创建一个新的AutowiredAnnotationBeanPostProcessor
* 尝试将@Autowired、@Value、@Inject的Class加入autowiredAnnotationTypes
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
//首先加入Autowired.class
this.autowiredAnnotationTypes.add(Autowired.class);
//然后加入Value.class
this.autowiredAnnotationTypes.add(Value.class);
try {
//最后加入javax.inject.Inject.class,如果存在(必须引入支持JSR-330 API的依赖)
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
} catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
如果determineConstructorsFromBeanPostProcessors方法找到的候选构造器数组不为null(这是查找注解,比如@Autowired注解),或者自动注入模式为构造器自动注入(这是XML设置的自动注入模式),或者XML定义了< constructor-arg/>标签,或者外部设置的参数args不为空。那么调用autowireConstructor进行构造器自动注入的方式创建bean实例。
autowireConstructor用于对于从候选构造器数组中选择合适的构造器实例化bean,并且可能进行构造器自动注入,返回被包装后的bean实例——BeanWrapper对象,实际类型为BeanWrapperImpl。
内部实际上是委托的ConstructorResolver构造器解析器的autowireConstructor方法来实现的。
/**
* 选择合适的构造器实例化bean,并且进行构造器自动注入,返回被包装后的bean实例——BeanWrapper对象。
*
* @param beanName beanName
* @param mbd bean definition
* @param ctors 候选构造器数组,可能为null
* @param explicitArgs 外部传递进来的构造器所需参数,如果没有传递,则为null
* @return 新实例的 Beanwrapper
*/
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
//内部实际上是委托的ConstructorResolver构造器解析器的autowireConstructor方法来实现的
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
/**
* ConstructorResolver的构造器
*
* 为给定的工厂和实例化策略创建新的构造器解析器
*/
public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.logger = beanFactory.getLogger();
}
因此,我们可以说ConstructorResolver的autowireConstructor方法才是核心方法,大概步骤为:
/**
1. ConstructorResolver的方法
2.
3. 选择合适的构造器实例化bean,并且进行构造器自动注入,返回被包装后的bean实例——BeanWrapper对象。
4. 5. @param beanName beanName
6. @param mbd 已合并的bean定义
7. @param chosenCtors 候选构造器数组,可能为null
8. @param explicitArgs 外部传递进来的构造器所需参数,如果没有传递,则为null
9. @return 新实例的 Beanwrapper
*/
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//实例化BeanWrapperImpl实例用来包装bean实例
BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化BeanWrapper,设置转换服务ConversionService,注册自定义的属性编辑器PropertyEditor
this.beanFactory.initBeanWrapper(bw);
//保存用来实例化的类的构造器
Constructor<?> constructorToUse = null;
//用来实例化的类的构造器参数Holder
ArgumentsHolder argsHolderToUse = null;
//用来实例化的类的构造器参数
Object[] argsToUse = null;
/*
* 1 尝试查找缓存,看是否存在已被解析的构造器和参数
*/
//如果外部参数不为null,一般都是null,即一般getBean方法不会指定参数
if (explicitArgs != null) {
//那么要使用的构造器参数,就等于外部传递的参数值
argsToUse = explicitArgs;
}
//否则,尝试查找缓存
else {
//argsToResolve用来表示需要解析的构造器参数
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//尝试直接获取已解析的构造器或工厂方法(resolvedConstructorOrFactoryMethod----用于缓存已解析的构造器或工厂方法)
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
//如果不为null,并且constructorArgumentsResolved为true,constructorArgumentsResolved表示构造器参数是否已被解析
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
//如果构造器已被解析并且参数已被解析,那么直接获取已解析的构造器参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
//如果获取到的已解析的构造器参数为null,则获取准备用于解析的构造器参数
//因为如果constructorArgumentsResolved为true,那么resolvedConstructorArguments
// 和preparedConstructorArguments必有一个不为null
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
//如果argsToResolve不为null
if (argsToResolve != null) {
//对缓存的构造器参数进行解析并进行类型转换,将结果赋值给argsToUse
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
/*
* 2 如果constructorToUse为null,或者argsToUse为null
* 表示缓存中没有已解析的构造器,需要解析构造器
*/
if (constructorToUse == null || argsToUse == null) {
//保存候选构造器
Constructor<?>[] candidates = chosenCtors;
//如果候选构造器数组为null,那么主动获取全部构造器作为候选构造器数组
//对于XML的配置,candidates就是null,基于注解的配置candidates可能不会为null
if (candidates == null) {
//获取beanClass
Class<?> beanClass = mbd.getBeanClass();
try {
//isNonPublicAccessAllowed判断是否允许访问非公共的构造器和方法
//允许的话就反射调用getDeclaredConstructors获取全部构造器,否则反射调用getConstructors获取公共的构造器
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);
}
}
/*
* 2.1 无参构造器解析,解析后会缓存解析结果,下次不会再次解析。
*/
//如果仅有一个候选构造器,并且外部没有传递参数,并且没有定义< constructor-arg >标签
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
//获取该构造器
Constructor<?> uniqueCandidate = candidates[0];
//如果该构造器没有参数,表示无参构造器,那简单,由于只有一个无参构造器
//那么每一次创建对象都是调用这个构造器,所以将其加入缓存中
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
//设置已解析的构造器缓存属性为uniqueCandidate
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
//设置已解析的构造器参数标志位缓存属性为true
mbd.constructorArgumentsResolved = true;
//设置已解析的构造器参数缓存属性为EMPTY_ARGS,表示空参数
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
/*
* 到这一步,已经确定了构造器与参数,随后调用instantiate方法,
* 传递beanName、mbd、uniqueCandidate、EMPTY_ARGS初始化bean实例,随后设置到bw的相关属性中
*/
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
//返回bw
return bw;
}
}
/*
* 2.2 解析有参构造器
*/
/*
* 2.2.1 判断是否需要自动装配
* 如果候选构造器数组不为null,或者自动注入的模式为AUTOWIRE_CONSTRUCTOR,即构造器注入
* 那么需要自动装配,autowiring设置为true
*/
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
//构造器参数值的持有者,通常作为 bean 定义的一部分
ConstructorArgumentValues resolvedValues = null;
/*
* 2.2.2 解析构造器参数,返回参数个数
*/
//minNrOfArgs表示构造器参数个数
int minNrOfArgs;
//如果外部传递进来的构造器参数数组不为null,那么minNrOfArgs等于explicitArgs长度
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
//否则,解析构造器参数,返回参数个数
else {
//获取bean定义中的constructorArgumentValues属性,前面解析标签的时候就说过了,这是对于全部子标签的解析时设置的属性
//保存了基于XML的子标签传递的参数的名字、类型、索引、值等信息,对于基于注解的配置来说cargs中并没有保存信息,返回空对象
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
//创建一个新的ConstructorArgumentValues,用于保存解析后的构造器参数,解析就是将参数值转换为对应的类型
resolvedValues = new ConstructorArgumentValues();
//解析构造器参数,minNrOfArgs设置为解析构造器之后返回的参数个数,对于基于注解配置的配置来说将返回0
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
/*
* 2.2.3 从候选构造器中选择合适的的构造器,以及构造参数
*/
//对候选构造器排序:主要按访问修饰符排序:public>protect>private,次要按构造器参数个数排序:参数多的排在前面
AutowireUtils.sortConstructors(candidates);
//最小的类型差异权重,值越小越匹配,初始化为int类型的最大值
int minTypeDiffWeight = Integer.MAX_VALUE;
//具有歧义的构造器集合
Set<Constructor<?>> ambiguousConstructors = null;
//收集异常的集合
LinkedList<UnsatisfiedDependencyException> causes = null;
/*
* 遍历排序之后的候选构造器集合,找到最符合的构造器
*/
for (Constructor<?> candidate : candidates) {
//获取当前构造器参数数量
int parameterCount = candidate.getParameterCount();
//如果缓存的已解析的构造器不为null,并且argsToUse不为null,并且参数长度大于parameterCount,即大于最大长度
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
//已经找到了最满足的贪婪构造器,因为当前构造器的参数个数已经是最多的了,不需要向后查找
break;
}
//如果当前构造器参数个数小于最少参数个数,那么视为当前构造器不满足要求,跳过这个构造器,遍历下一个
if (parameterCount < minNrOfArgs) {
continue;
}
//参数数组持有者
ArgumentsHolder argsHolder;
//获取当前构造器的参数类型数组
Class<?>[] paramTypes = candidate.getParameterTypes();
/*如果resolvedValues不为null,表示已解析构造器参数*/
if (resolvedValues != null) {
try {
//获取当前构造器上的@ConstructorProperties注解标注的构造器参数名数组,这个注解的作用之一就是可以通过指定名称来改变xml文件中constructor-arg的name属性
//这是JDK 1.6提供的注解,位于rt.jar包中。注意这不是指定别名,如果指定了@ConstructorProperties注解那么只能使用该注解指定的名字,这个注解基本没人用了
String[] paramNames = ConstructorResolver.ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
//如果获取的paramNames为null,表示该构造器上不存在@ConstructorProperties注解,基本上都会走这个逻辑
if (paramNames == null) {
//获取AbstractAutowireCapableBeanFactory中的parameterNameDiscoverer
//参数名解析器,默认不为null,是DefaultParameterNameDiscoverer实例
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//由于没有@ConstructorProperties注解,那么获取构造器上的参数名作为匹配的名称
paramNames = pnd.getParameterNames(candidate);
}
}
//通过给定已解析的构造器参数值,创建参数数组以调用构造器或工厂方法,返回参数数组持有者
//getUserDeclaredConstructor返回原始类的构造器,通常就是本构造器,除非是CGLIB生成的子类
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
} catch (UnsatisfiedDependencyException ex) {
//如果参数匹配失败
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// 保存匹配失败的异常信息,并且下一个构造器的尝试
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
//结束本次循环继续下一次循环
continue;
}
}
/*
* 如果resolvedValues为null,表示通过外部方法显式指定了参数
* 比如getBean方法就能指定参数数组
*/
else {
// Explicit arguments given -> arguments length must match exactly.
//如果构造器参数数量不等于外部方法显式指定的参数数组长度,那么直接结束本次循环继续下一次循环,尝试匹配下一个构造器
if (parameterCount != explicitArgs.length) {
continue;
}
//如果找到第一个参数长度相等的构造器,那么直接创建一个ArgumentsHolder
argsHolder = new ArgumentsHolder(explicitArgs);
}
/*
* 类型差异权重计算
*
* isLenientConstructorResolution判断当前bean定义是以宽松模式还是严格模式解析构造器,工厂方法使用严格模式,其他默认宽松模式(true)
* 如果是宽松模式,则调用argsHolder的getTypeDifferenceWeight方法获取类型差异权重,宽松模式使用具有最接近的类型进行匹配
* getTypeDifferenceWeight方法用于获取最终参数类型arguments和原始参数类型rawArguments的差异,但是还是以原始类型优先,
* 因为原始参数类型的差异值会减去1024,最终返回它们的最小值
*
* 如果是严格模式,则调用argsHolder的getAssignabilityWeight方法获取类型差异权重,严格模式下必须所有参数类型的都需要匹配(同类或者子类)
* 如果有任意一个arguments(先判断)或者rawArguments的类型不匹配,那么直接返回Integer.MAX_VALUE或者Integer.MAX_VALUE - 512
* 如果都匹配,那么返回Integer.MAX_VALUE - 1024
*
*
*/
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 如果typeDiffWeight小于minTypeDiffWeight,表示此构造器是最接近的匹配项,那么选择此构造器
if (typeDiffWeight < minTypeDiffWeight) {
//设置属性值
constructorToUse = candidate;
argsHolderToUse = argsHolder;
//最终使用的参数值为argsHolder的arguments数组
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
// 否则,如果constructorToUse不为null,并且typeDiffWeight等于minTypeDiffWeight,即权重相等
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
//添加到具有歧义的ambiguousConstructors集合中
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
/*
* 2.2.4 遍历全部构造器完毕,可能找到了最合适的构造器,可能没找到,进行后续处理
*/
/*如果遍历全部候选构造器集合之后还是没找到将要使用的构造器,抛出异常*/
if (constructorToUse == null) {
//causes异常集合不为null,
if (causes != null) {
//获取并移除最后一个抛出的异常
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
//抛出该异常
throw ex;
}
//抛出异常:Could not resolve matching constructor……
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
/*
* 如果找到了将要使用的构造器,但是ambiguousConstructors也不为null,说明存在相同的权重的构造器
* 并且,如果isLenientConstructorResolution返回false,即严格模式
* 那么抛出异常:Ambiguous constructor matches found in bean……
*/
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);
}
//没有抛出异常,如果外部参数为null,并且找到的用来实例化对象的构造器参数不为null
if (explicitArgs == null && argsHolderToUse != null) {
//那么将解析的构造器和参数存入缓存
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
/*
* 3 最终调用instantiate方法,根据有参构造器和需要注入的依赖参数进行反射实例化对象,并将实例化的对象存入当前bw的缓存中
*/
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
BeanWrapperImpl是Spring中一个很重要的体系,在创建bean实例的过程中有很大的作用。它内部包含了被封装后待处理的bean和用于设置bean属性的属性编辑器,专门用来构建所需的对象,即populateBean的填充属性操作(下篇文章会将)。它的uml类图结构如下:
我们简单介绍一下该体系的成员:
new BeanWrapperImpl用于创建新的空 BeanWrapperImpl,包装实例需要随后设置。注册默认编辑器editors,用于类型转换!
设置PropertyEditorRegistrySupport的defaultEditorsActive属性值为true,表示激活默认的PropertyEditor。
/**
* 创建新的空 BeanWrapperImpl。包装实例需要随后设置。 注册默认编辑器editors。
*/
public BeanWrapperImpl() {
this(true);
}
/**
* 创建新的空 BeanWrapperImpl。包装实例需要随后设置。
*
* @param registerDefaultEditors 是否注册默认编辑器(如果 BeanWrapper 不需要任何类型转换,可以禁止)
*/
public BeanWrapperImpl(boolean registerDefaultEditors) {
//调用父类AbstractNestablePropertyAccessor的构造器
super(registerDefaultEditors);
}
/**
* AbstractNestablePropertyAccessor的构造器
* 它是ConfigurablePropertyAccessor(可配置的属性访问器)的基本实现
*
* 创建新的空访问器。包装实例需要随后设置。
*
* @param registerDefaultEditors 是否注册默认编辑器(如果 BeanWrapper 不需要任何类型转换,可以禁止)
*/
protected AbstractNestablePropertyAccessor(boolean registerDefaultEditors) {
//如果registerDefaultEditors为true,那么注册默认的Editor
if (registerDefaultEditors) {
//调用父类PropertyEditorRegistrySupport的方法
registerDefaultEditors();
}
//设置父类TypeConverterSupport的属性,用于将属性值转换为目标类型的内部帮助器类。
this.typeConverterDelegate = new TypeConverterDelegate(this);
}
/**
* PropertyEditorRegistrySupport的属性,默认为false
*/
private boolean defaultEditorsActive = false;
/**
* PropertyEditorRegistrySupport的方法
*
* 激活此注册表实例的默认编辑器,允许根据需要懒加载地注册默认编辑器。
*/
protected void registerDefaultEditors() {
//设置为true
this.defaultEditorsActive = true;
}
初始化刚创建的BeanWrapper实例,主要是为当前的BeanWrapperImpl实例设置转换服务ConversionService以及注册自定义的属性编辑器PropertyEditor。
普通spring项目不会自动注册默认的ConversionService的bean,因此默认基于PropertyEditor进行类型转换。而boot项目则默认自动注册一个ApplicationConversionService服务。
我们自定义的PropertyEditor最开始是存放到beanFactory的propertyEditorRegistrars与customEditors这两个缓存集合中的,一个用于存放PropertyEditorRegistrar即自定义属性编辑器注册表,另一个用于直接存放自定义属性编辑器。这里的registerCustomEditors方法就是将beanFactory中的这两个缓存中的PropertyEditor存入PropertyEditorRegistrySupport(当前BeanWrapperImpl实例)的overriddenDefaultEditors和customEditors缓存中。
/**
* AbstractBeanFactory的方法
*
* 使用在此工厂注册的自定义编辑器初始化给定的 BeanWrapper。为创建和填充 Bean 实例的 BeanWrapper 调用。
*
* @param bw BeanWrapper
*/
protected void initBeanWrapper(BeanWrapper bw) {
//获取AbstractBeanFactory的conversionService属性值设置给BeanWrapper的父类PropertyEditorRegistrySupport的conversionService属性
//将会使用Spring 3.0 引入的用于转换属性值的转换服务,作为 JavaBeans PropertyEditors(属性编辑器)的替代服务
//普通spring项目不会自动注册ConversionService bean,因此默认基于PropertyEditor。boot项目默认自动注册ApplicationConversionService服务
bw.setConversionService(getConversionService());
//使用已在此 BeanFactory 注册的自定义编辑器初始化给定的PropertyEditorRegistry中,即初始化bw
registerCustomEditors(bw);
}
/**
* AbstractBeanFactory的方法
*
* 使用已在此 BeanFactory 注册的自定义编辑器初始化给定的PropertyEditorRegistry。
*
* 为创建和填充 Bean 实例的 BeanWrapper 调用,以及用于构造器参数和工厂方法类型转换的SimpleTypeConverter。
*
* @param registry 属性编辑器注册初始化
*/
protected void registerCustomEditors(PropertyEditorRegistry registry) {
//转换为PropertyEditorRegistrySupport类型,我们前面讲过,BeanWrapperImpl算作PropertyEditorRegistrySupport的子类
PropertyEditorRegistrySupport registrySupport =
(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
//如果不为null
if (registrySupport != null) {
//将PropertyEditorRegistrySupport的configValueEditorsActive属性设置为true,即激活仅用于配置目的的配置值编辑器,比如StringArrayPropertyEditor
//默认情况下,这些编辑器不会被注册,因为它们通常不适合数据绑定目的。当然,在任何情况下,都可以调用registerCustomEditor手动注册
registrySupport.useConfigValueEditors();
}
/*
* 1 如果AbstractBeanFactory的propertyEditorRegistrars缓存不为空,即存在自定义属性编辑器注册表,那么需要将这些注册表中的编辑器注册到给定的registry中
*
* 在前面讲过的prepareBeanFactory方法中,就向propertyEditorRegistrars缓存中注册了一个ResourceEditorRegistrar的注册表实例
* customEditors默认就是只有一个注解表,就是ResourceEditorRegistrar。我们在扩展Spring的时候,比如扩展prepareBeanFactory方法
* 更常见的是实现BeanFactoryPostProcessor接口,可以调用 beanFactory.addPropertyEditorRegistrar方法注册自定义的属性编辑器注册表到propertyEditorRegistrars缓存中
* Spring提供了一个专门配置自定义属性编辑器的BeanFactoryPostProcessor接口实现CustomEditorConfigurer,我们直接使用即可
*/
if (!this.propertyEditorRegistrars.isEmpty()) {
//遍历注册表
for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
try {
//将注册表中的全部自定义的编辑器注册到给定的registry的缓存中
//实际上是存入PropertyEditorRegistrySupport的overriddenDefaultEditors缓存中
registrar.registerCustomEditors(registry);
} catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) {
if (logger.isDebugEnabled()) {
logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
"] failed because it tried to obtain currently created bean '" +
ex.getBeanName() + "': " + ex.getMessage());
}
onSuppressedException(ex);
continue;
}
}
throw ex;
}
}
}
/*
* 2 如果AbstractBeanFactory的customEditors缓存不为空,即存在自定义属性编辑器,那么需要将这些自定义的编辑器注册到给定的registry中
*
* customEditors默认就是空集合,我们在扩展Spring的时候,比如扩展prepareBeanFactory方法,比如BeanFactoryPostProcessor接口
* 更常见的是实现BeanFactoryPostProcessor接口,可以调用 beanFactory.registerCustomEditor方法注册自定义的属性编辑器到customEditors缓存中
* Spring提供了一个专门配置自定义属性编辑器的BeanFactoryPostProcessor接口实现CustomEditorConfigurer,我们直接使用即可
*/
if (!this.customEditors.isEmpty()) {
//遍历该集合
this.customEditors.forEach((requiredType, editorClass) ->
//将自定义的编辑器注册到给定的registry的缓存中
//实际上是存入PropertyEditorRegistrySupport的customEditors缓存中
registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
}
}
如果XML中指定了自动注入的类型,那么就返回指定的类型,否则默认不自动注入的模式,即使用了自动注入注解,即该属性是专为XML配置服务的。
如果设置的是自动选择注入模式,那就看它有没有无参构造器,如果有,则byType自动注入,否则将使用构造器自动注入(constructor)。Spring 3.0开始,不推荐使用XML配置自动选择注入模式,如果要自动选择,应该使用注解的方式,比如@Autowired。
/**
* AbstractBeanDefinition的方法
*
* 返回已解析的自动装配类型
*/
public int getResolvedAutowireMode() {
//是否是自动选择注入模式,Spring 3.0开始,不推荐使用该模式,而是使用注解的方式
if (this.autowireMode == AUTOWIRE_AUTODETECT) {
//如果它有无参构造器,则byType自动注入,否则将尝试构造器自动注入(constructor)。
Constructor<?>[] constructors = getBeanClass().getConstructors();
for (Constructor<?> constructor : constructors) {
//如果存在无参构造器,那么使用byType自动注入
if (constructor.getParameterCount() == 0) {
return AUTOWIRE_BY_TYPE;
}
}
//否则使用constructor自动注入
return AUTOWIRE_CONSTRUCTOR;
}
else {
//如果指定了自动注入的类型,那么就返回指定的类型,默认不自动注入
return this.autowireMode;
}
}
resolveConstructorArguments方法用于解析bean定义中的构造器参数,将解析之后的构造器参数使用一个新的ConstructorArgumentValues属性resolvedValues保存,并返回构造器参数的数量。默认就是在XML中配置的< constructor-arg>子标签数量,因此对于基于注解的配置来说将返回0。
之前解析< constructor-arg/>标签时,我们将全部< constructor-arg/>标签标签解析、封装为一个constructorArgumentValues属性,保存了基于XML的< constructor-arg/>子标签传递的参数的名字、类型、索引、值等信息,同时将对应的值的转换为了不同的包装类,比如设置值为< list/>标签,那么转换为ManagedArray,如果设置值为< idref/>标签,那么转换为RuntimeBeanNameReference,如果设置值为ref属性引用其他bean,那么转换为RuntimeBeanReference,这部分在parseConstructorArgElements和parsePropertyValue有讲解。注意对于基于注解的配置来说constructorArgumentValues属性中并没有保存信息。
这里的resolveConstructorArguments方法就是将之前的值包装类转换为对应的实例Java类型(这里的类型并不是属性的具体类型),比如ManagedArray转换为数组,ManagedList转换为list集合,如果是引用其他bean或者指定了另一个bean定义,比如RuntimeBeanReference,则在这里会先初始化该引用的bean实例并返回,注意构造器注入没有循环依赖,但是方法注入和注解注入可能有循环依赖,这里就会处理,后面再说。
/**
* AbstractBeanFactory的属性
*
* 一个自定义的TypeConverter实现,将会覆盖重写默认属性编辑器机制,默认为null
*/
@Nullable
private TypeConverter typeConverter;
/**
* ConstructorResolver的方法
*
* 将此 bean 的构造器参数解析为resolvedValues对象。这可能涉及查找、初始化其他bean类实例
* 此方法还用于处理静态工厂方法的调用。
*/
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
//获取AbstractBeanFactory中的typeConverter自定义类型转换器属性,该属性用来覆盖默认属性编辑器PropertyEditor
//并没有提供getCustomTypeConverter方法的默认返回,因此customConverter默认返回null,我们同样可以自己扩展
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
//如果自定义类型转换器customConverter不为null,那么就使用customConverter
//否则使用bw对象本身,因为BeanWrapper也能实现类型转换,一般都是使用bw本身
//这个converter用于解析TypedStringValues,将String类型转换为其他类型
TypeConverter converter = (customConverter != null ? customConverter : bw);
//初始化一个valueResolver对象,用于将 bean 定义对象中包含的值解析为应用于目标 bean 实例的实际值
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
//minNrOfArgs初始化为cargs内部的的indexedArgumentValues和genericArgumentValues两个集合的元素总数量
//即XML的bean定义中的标签的数量
int minNrOfArgs = cargs.getArgumentCount();
/*
* 遍历、解析cargs的indexedArgumentValues集合,即带有index属性的标签解析之后存放的map集合
*/
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
//获取key,key就是index
int index = entry.getKey();
if (index < 0) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
//如果index大于minNrOfArgs,则minNrOfArgs=index + 1,因为index从0开始的
if (index + 1 > minNrOfArgs) {
minNrOfArgs = index + 1;
}
//获取已经解析的子标签
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
//判断是否已经转换过值类型,默认是没有转换的
if (valueHolder.isConverted()) {
//如果已经转换过,直接添加到resolvedValues对象的indexedArgumentValues集合中
resolvedValues.addIndexedArgumentValue(index, valueHolder);
}
//如果没有转换过,那么需要转换
else {
/*
* 之前解析子标签时,Spring会将对应的值的转换为了不同的包装类,比如设置值为标签,那么转换为ManagedArray
* 如果设置值为标签,那么转换为RuntimeBeanNameReference,如果设置值为ref属性引用其他bean,那么转换为RuntimeBeanReference
* 这部分在parseConstructorArgElements和parsePropertyValue有讲解
*
* 这里的resolveValueIfNecessary方法,则是将之前的值包装类转换为对应的实例Java类型,比如ManagedArray转换为数组、ManagedList转换为list集合
* 如果是引用其他bean或者指定了另一个bean定义,比如RuntimeBeanReference,则在这里会先初始化该引用的bean
* 实例并返回,注意构造器注入没有循环依赖,但是方法注入和注解注入可能有循环依赖,这里就会处理,后面再说
* 相当于反解回来,这里的resolvedValue就是转换后的实际Java类型,这就是所谓的转换,这也是前面所说的运行时解析,就是这个逻辑
*
* 这里的argName传递的就是一个"constructor argument"字符串,实际上在解析构造器参数时这个参数没啥作用
* 但是resolveValueIfNecessary方法同样用于property的解析,那时就会传递propertyName
*/
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
//重新创建一个新的resolvedValueHolder,设置value值为解析之后的值resolvedValue
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
//设置源
resolvedValueHolder.setSource(valueHolder);
//将解析之后的resolvedValueHolder添加到resolvedValues对象的indexedArgumentValues集合中
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
/*
* 遍历、解析cargs的genericArgumentValues集合,即不带index属性的标签解析之后存放的集合
*/
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
//判断是否已经转换过值类型,默认是没有转换的
if (valueHolder.isConverted()) {
//如果已经转换过,直接添加到resolvedValues对象的genericArgumentValues集合中
resolvedValues.addGenericArgumentValue(valueHolder);
}
//如果没有转换过,那么需要转换,和上面的逻辑是一样的
else {
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
//将解析之后的resolvedValueHolder添加到resolvedValues对象的genericArgumentValues集合中
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
//返回minNrOfArgs
return minNrOfArgs;
}
循环遍历所有的候选构造器,调用createArgumentArray方法用于通过给定的构造器以及已解析的构造器参数值以及参数名和类型等参数尝试创建属于该构造器的参数值数组,用于后面调用构造器或工厂方法,返回一个参数值数组持有者ArgumentsHolder。
该方法进一步解析前面“已解析”的resolvedValues,简单的说,就是尝试将配置的已解析的参数值与构造器的参数类型匹配,甚至尝试将解析后的类型进一步转换为参数所需的类型。如果允许构造器自动装配,那么当没有在配置的构造器值中与构造器参数匹配成功时还会调用resolveAutowiredArgument方法在容器中进行的依赖查找,因此这一步将可能进行其他bean的初始化。
如果某个构造器的某个参数不能与手动配置的参数值匹配,并且(没有设置构造器自动装配或者设置了构造器自动装配但是没有在容器中找到匹配的bean),那么该方法将抛出UnsatisfiedDependencyException异常。随后外部的autowireConstructor方法会捕获这个异常并记录,然后会进行后续的构造器的匹配,如果后续有构造器匹配成功那么这个异常最终不被抛出,如果所有构造器都匹配失败,那么就会抛出相关异常。
最后,将通过resolveAutowiredArgument方法找到的需要注入依赖的beanName集合autowiredBeanNames中的beanName以及需要创建的对象的beanName的依赖关系调用registerDependentBean方法注册到dependentBeanMap和dependenciesForBeanMap缓存中。因为对于从容器中查找到的自动注入的bean也算作当前bean依赖的bean。
如果正常返回,那么返回的ArgumentsHolder中保存了后续可能会调用该构造器时需要传递的参数。
/**
* ConstructorResolver的方法
*
* 使用给定已解析的构造器参数值,创建参数数组以调用构造器或工厂方法,返回参数数组持有者
*
* @param beanName beanName
* @param mbd 已合并的bean定义
* @param resolvedValues 已解析的构造器参数
* @param bw 当前bean包装对象
* @param paramTypes 当前的构造器的参数类型数组
* @param paramNames 当前的构造器的参数名称
* @param executable 原始构造器
* @param autowiring 是否自动注入
* @param fallback 存在超过一个候选构造器,那么为false,如果只有一个候选构造器,那么为true
*/
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
/*获取类型转换器,如果没有自定义类型转换器就是用当前bw*/
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
//创建ArgumentsHolder对象用于存放参数数组
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
//已使用过的 ValueHolder 对象集,一个ValueHolder只能匹配一个参数
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
//自动注入的beanName的集合,用于注册依赖关系
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
/*
* 遍历参数类型数组
*/
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
//获取参数类型以及对应的参数名
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
//从XML配置的参数中查找与当前遍历参数匹配的参数valueHolder
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
//根据index属性、name属性、type属性匹配一个没有被使用过的valueHolder
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
//如果没找到匹配的valueHolder,并且(不是自动注入,或者参数类型长度等于已解析的配置参数个数),那么需要进一步从已配置的参数中选取可以匹配的参数
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
//在genericArgumentValues中查找一个没有被使用过的valueHolder,暂不匹配type和name
//以期望他可以在后面的匹配中,在类型转换后匹配(例如,String -> int)
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
/*如果valueHolder不为null,表示找到了一个潜在的匹配,下面尝试它到底行不行*/
if (valueHolder != null) {
//添加到已使用的usedValueHolders集合,
usedValueHolders.add(valueHolder);
//获取原始的originalValue
Object originalValue = valueHolder.getValue();
//已转换的convertedValue
Object convertedValue;
//如果当前valueHolder已转换过
if (valueHolder.isConverted()) {
//直接获取convertedValue集合
convertedValue = valueHolder.getConvertedValue();
//设置args的preparedArguments准备参数数组对应的索引的值为convertedValue
args.preparedArguments[paramIndex] = convertedValue;
}
//否则,需要转换
else {
//根据构造器(方法)和参数索引获取一个MethodParameter工具类对象
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
//转换类型,尝试将originalValue转换为paramType类型,并且作为转换目标的methodParam方法参数(用于泛型匹配)
//这里才是尝试将已解析的构造器值继续转换为参数类型的逻辑,在上面的resolveConstructorArguments中仅仅是将值得包装对象解析为Java值类型而已
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
} catch (TypeMismatchException ex) {
//转换失败抛出异常
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
//获取最开始的源
Object sourceHolder = valueHolder.getSource();
//如果是ConstructorArgumentValues.ValueHolder类型
//因为这里的resolvedValues都是由最开始的ValueHolder转换来的,因此该判断满足
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
//获取原值
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
//设置resolveNecessary属性为true,表示需要解析
args.resolveNecessary = true;
//设置args的preparedArguments准备参数数组对应的索引的值为sourceValue
args.preparedArguments[paramIndex] = sourceValue;
}
}
//设置args的arguments参数数组对应的索引的值为convertedValue
args.arguments[paramIndex] = convertedValue;
//设置args的arguments原始参数数组对应的索引的值为originalValue
args.rawArguments[paramIndex] = originalValue;
}
/*如果valueHolder为null,表示没找到匹配的参数*/
else {
//根据构造器(方法)和参数索引获取一个MethodParameter工具类对象
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
//如果既没有匹配到配置的参数也不是自动装配,那么说明装配失败,抛出异常:Ambiguous argument values for parameter ……
//这个异常我相信很多人都见过吧!但是,这个异常并不一定会最终抛出,外面的autowireConstructor方法会捕获这个异常并做好记录
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
/*
* 到这一步还没抛出异常,说明是自动装配,这时需要到容器中去查找满足匹配条件的值
* 最常见的就是@Autowired修饰构造器,它的参数依赖注入就是在这个逻辑中完成的
*/
try {
//构造器自动装配核心方法,到容器中去查找满足匹配条件的值,将会返回找到的满足条件的bean实例
//这一步将可能触发其他bean定义的初始化
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
//解析出来的值赋值给args
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
} catch (BeansException ex) {
//解析失败抛出异常,同样这个异常并不一定会最终抛出,外面的autowireConstructor方法会捕获这个异常并做好记录
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
/*遍历自动注入的beanName,这些bean也算作当前bean定义依赖的bean*/
for (String autowiredBeanName : autowiredBeanNames) {
//那么将autowiredBeanName和beanName的依赖关系注册到dependentBeanMap和dependenciesForBeanMap缓存中
//这个方法我们在前面就讲过了
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
如果在XML配置的属性值中没找到匹配参数的值,并且支持自动注入(候选构造器数组不为null,或者XML配置的自动注入的模式为AUTOWIRE_CONSTRUCTOR,即构造器注入),那么会调用该方法。该方法会到容器中去查找,将会返回找到的满足条件的bean实例,这一步将可能触发其他bean定义的初始化,这是构造器自动装配核心方法。
该方法是一个中间方法,内部还是委托beanFactory的resolveDependency方法来解析依赖。返回将被注入的依赖!
需要注意的是,如果只有一个候选构造器,那么对于集合类型的参数即使没有找到适合的依赖也会返回一个对应类型的空集,如果有多个候选构造器并且没找到候选依赖,则正常抛出NoSuchBeanDefinitionException异常到createArgumentArray方法中!
/**
1. ConstructorResolver的方法
2.
3. 用于解析自动装配的指定参数的模板方法。
4. 5. @param beanName beanName
6. @param param 构造器指定位置的参数对象
7. @param autowiredBeanNames 自动注入的beanName的集合
8. @param typeConverter 类型转换器
9. @param fallback 存在超过一个候选构造器,那么为false,如果只有一个候选构造器,那么为true
*/
@Nullable
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
//获取参数类型
Class<?> paramType = param.getParameterType();
//如果参数类型是InjectionPoint类型及其子类型,一般都不是
if (InjectionPoint.class.isAssignableFrom(paramType)) {
//获取当前的InjectionPoint,并返回
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
throw new IllegalStateException("No current InjectionPoint available for " + param);
}
return injectionPoint;
}
try {
//内部委托beanFactory的resolveDependency方法来解析依赖
//传递一个DependencyDescriptor依赖描述符,它表示一个注入点信息,可能是一个字段或者方法参数,这里它的required属性都为true,表示是必须的依赖
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
} catch (NoUniqueBeanDefinitionException ex) {
throw ex;
} catch (NoSuchBeanDefinitionException ex) {
//如果只有一个候选构造器,那么对于集合类型应该返回一个空集
if (fallback) {
//如果依赖类型为数组,那么返回一个空数组
if (paramType.isArray()) {
return Array.newInstance(paramType.getComponentType(), 0);
}
//如果依赖类型为Collection,那么返回一个对应依赖类型的空Collection
else if (CollectionFactory.isApproximableCollectionType(paramType)) {
return CollectionFactory.createCollection(paramType, 0);
}
//如果依赖类型为Map,那么返回一个对应依赖类型的空Map
else if (CollectionFactory.isApproximableMapType(paramType)) {
return CollectionFactory.createMap(paramType, 0);
}
}
//如果有多个候选构造器,那么抛出异常
throw ex;
}
}
这是DefaultListableBeanFactory实现的方法,根据此工厂中的 bean定义解析指定的依赖项,简单的说就是从容器中查找符合的bean实例并返回,找不到就可能会抛出异常。
DependencyDescriptor封装了一个依赖注入点的信息,可以封装一个方法参数信息MethodParameter,也可以封装一个字段参数Field。
下面我们会仔细讲解getLazyResolutionProxyIfNecessary和doResolveDependency方法。
/**
1. DefaultListableBeanFactory的方法
2.
3. 根据此工厂中的 bean定义 解析指定的依赖项。
4. 5. @param descriptor 即将注入的特定依赖项的描述符,包含MethodParameter的信息,也可以百奥是一个字段
6. @param requestingBeanName beanName
7. @param autowiredBeanNames 自动注入的beanName的集合
8. @param typeConverter 类型转换器
9. @return 找到的依赖实例
*/
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//初始化descriptor
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
/*1 如果依赖的类型为Optional类型,Java8的新特性,可以避免由于没有找到依赖而抛出异常*/
if (Optional.class == descriptor.getDependencyType()) {
//那么返回一个被Optional包装的依赖项,因此允许找不到依赖项,也就不会抛出异常了,这个我们在IoC学习的时候已经讲过了
return createOptionalDependency(descriptor, requestingBeanName);
}
/*2 如果依赖的类型为ObjectFactory类型或者ObjectProvider类型*/
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
//返回一个DependencyObjectProvider对象,这是一个可序列化ObjectFactory/ObjectProvider提供器,用于延迟解决依赖项。
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
/*3 如果依赖的类型为javax.inject.Provider类型*/
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
//返回一个Jsr330Factory对象
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
/*4 如果依赖的类型为其它类型,那么走下面的逻辑,这也是大部分的逻辑*/
else {
//获取autowireCandidateResolver,调用getLazyResolutionProxyIfNecessary方法,如果有必要(存在@Lazy注解),则获取延迟加载的代理对象
//Spring不能自己解决构造器循环依赖,但是,我们添加@Lazy注解即可解决构造器循环依赖,其实现就是返回代理对象,走的就是这个逻辑
//autowireCandidateResolver默认是SimpleAutowireCandidateResolver类型的实例,那么该方法固定返回null,如果开启了注解支持
//那么在前面讲的registerAnnotationConfigProcessors方法中会默认注入的是一个ContextAnnotationAutowireCandidateResolver实例
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
//如果结果为null,表示没有延迟加载
if (result == null) {
//调用doResolveDependency解析依赖,获取依赖的对象,这一步可能会初始化所依赖的bean
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
//返回result
return result;
}
}
如果构造器或者参数上标注了@Lazy注解,那么getLazyResolutionProxyIfNecessary方法将返回一个代理对象,根据依赖的类型自动选择走JDK动态代理还是CGLIB代理。
该方法用于手动解决构造器循环依赖注入(当然这需要注解注册bean,否则还是会报错),依靠的就是@Lazy注解,由于返回的是代理对象,不需要立即创建目标对象,因此可以解决构造器的循环依赖。
如何判断是否需要返回代理对象:
/**
* ContextAnnotationAutowireCandidateResolver的方法
*
* 如果是延迟加载(设置了@Lazy注解)那么返回延迟加载的代理对象,如果不是那么返回null
* 可以解决构造器循环注入,这里实际上就是AOP的思想的应用了
*
* @param descriptor 依赖项的描述符,包含MethodParameter的信息
* @param beanName beanName
* @return 如果是延迟加载那么返回延迟加载的代理对象,如果不是那么返回null
*/
@Override
@Nullable
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
//判断是否是延迟加载的,如果是那么返回代理对象,如果不是那么返回null
return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}
/**
* ContextAnnotationAutowireCandidateResolver的方法
*
* @param descriptor 依赖项的描述符,包含MethodParameter的信息
* @return 是否设置了延迟加载
*/
protected boolean isLazy(DependencyDescriptor descriptor) {
//获取、遍历descriptor中包装的字段,或者方法/构造器的对应参数上关联的注解
for (Annotation ann : descriptor.getAnnotations()) {
//是否含有@Lazy注解
Lazy lazy = AnnotationUtils.getAnnotation(ann, Lazy.class);
//如果具有@Lazy注解,并且设置为true,那么返回true
if (lazy != null && lazy.value()) {
return true;
}
}
//获取包装的MethodParameter,即方法/构造器参数
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
//获取方法,如果参数属于构造器那么返回null
Method method = methodParam.getMethod();
//如果method为null或者返回值为null
//表示如果是构造器,或者是方法但是返回值为void,那么符合要求,可以进一步尝试
if (method == null || void.class == method.getReturnType()) {
//获取方法或者构造器上的@Lazy注解
Lazy lazy = AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);
//如果具有@Lazy注解,并且设置为true,那么返回true
if (lazy != null && lazy.value()) {
return true;
}
}
}
//返回false
return false;
}
buildLazyResolutionProxy方法将返回一个代理对象,根据依赖的类型自动选择走JDK动态代理还是CGLIB代理。
返回的代理对象并没有目标对象的属性或者方法,因此可以用于解决循环依赖。那么在后续使用时是,是怎么通过代理对象访问目标对象的属性或者方法的呢?能访问目标对象的核心就是在于该代理对象保存了一个TargetSource对象,这个TargetSource对象代表着一个AOP的目标对象也就是被代理对象,具有获取目标对象的getTarget方法,因此代理对象可以获取内部保存的TargetSource对象,进而调用getTarget方法获取目标对象,也就是被代理对象,从而调用该目标对象的方法或者属性。
比如对于CGLIB代理对象,它的类型为CglibAopProxy,当调用代理的方法时实际上就会调用通用intercept方法,该方法中会获取TargetSource对象并调用getTarget方法返回目标对象,最终调用目标对象的方法,这也是Spring AOP的大概逻辑。
buildLazyResolutionProxy这部分代理涉及到了Spring AOP的源码,建议大家可以去看看AOP的源码部分!
在buildLazyResolutionProxy方法中,创建的TargetSource的getTarget方法的核心实现还是调用的beanFactory的doResolveDependency方法获取目标对象,因此doResolveDependency方法也很重要,下面就会解析。
/**
* ContextAnnotationAutowireCandidateResolver的方法
*
* 构建延迟加载的代理对象
*
* @param descriptor 依赖项的描述符,包含MethodParameter的信息
* @param beanName beanName
* @return 代理对象
*/
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,
"BeanFactory needs to be a DefaultListableBeanFactory");
final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
//AOP的核心对象之一TargetSource,它表示"目标源",包装了目标对象(被代理的对象)
TargetSource ts = new TargetSource() {
//目标类型
@Override
public Class<?> getTargetClass() {
return descriptor.getDependencyType();
}
@Override
public boolean isStatic() {
return false;
}
//获取目标对象,在代理中就是通过该方法获取目标对象并调用目标对象的方法的
@Override
public Object getTarget() {
//同样调用beanFactory.doResolveDependency方法去解析依赖的对象,获取目标对象,这里返回的是真正的Spring bean对象
Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
if (target == null) {
Class<?> type = getTargetClass();
if (Map.class == type) {
return Collections.emptyMap();
} else if (List.class == type) {
return Collections.emptyList();
} else if (Set.class == type || Collection.class == type) {
return Collections.emptySet();
}
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
"Optional dependency not present for lazy injection point");
}
return target;
}
@Override
public void releaseTarget(Object target) {
}
};
//创建代理工厂
ProxyFactory pf = new ProxyFactory();
//设置目标源,从目标源中获取代理目标实例
pf.setTargetSource(ts);
//获取依赖类型
Class<?> dependencyType = descriptor.getDependencyType();
//如果是接口,那么加入到interfaces集合中,后面就可能会使用JDK动态代理
if (dependencyType.isInterface()) {
pf.addInterface(dependencyType);
}
//通过ProxyFactory生成代理对象,根据情况使用JDK代理或者CGLIB代理
return pf.getProxy(beanFactory.getBeanClassLoader());
}
可以看到无论是代理对象还是非代理对象,内部都涉及到doResolveDependency方法,在解析注解注入的后处理器比如CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor中都也会调用该方法,足以说明该方法的重要性。
以do开头的方法,是真正的根据此工厂中的 bean定义解析指定的依赖项的方法的实现。当然,它的实现更加复杂一点,它会从各种情况中获取依赖,除了从IoC容器查找之外还有从@Value注解中查找,并且它的优先级更高。
实际上,很多的自动注入模式的依赖查找都调用了该方法,除了目前正在讲的基于XML和注解配置的构造器自动注入之外,后面我们会讲到的@Autowired注解的setter方法注入、属性反射注入,XML配置的基于byType的setter方法自动注入(直接调用外层resolveDependency方法,并且不会走最后的banName查找),@Resource注解的byType注入(直接调用外层resolveDependency方法)等等注入逻辑内部也都会调用该方法。其他自动注入模式,比如XML配置的基于byName的setter方法自动注入则有自己的逻辑。因此,该方法尤为重要!
该方法的大概查找过程如下:
/**
1. DefaultListableBeanFactory的方法
2.
3. 从各种方面解析依赖
4. 5. @param descriptor 即将注入的特定依赖项的描述符,包含MethodParameter或者Filed的信息
6. @param beanName beanName
7. @param autowiredBeanNames 自动注入的beanName的集合
8. @param typeConverter 类型转换器
9. @return 找到的依赖
*/
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//设置当前的descriptor作为InjectionPoint,返回前一个InjectionPoint
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
/*
* 1 根据名称快速查找依赖项
* 如果当前descriptor为ShortcutDependencyDescriptor类型,那么相当于直接调用beanFactory.getBean(String name, Class requiredType)方法
* 一般都是DependencyDescriptor类型,因此会返回null,只有AutowiredAnnotationBeanPostProcessor中会用到ShortcutDependencyDescriptor
* AutowiredAnnotationBeanPostProcessor用于解析字段或者方法上的@Autowired、@Value、@Inject等注解,也是进行依赖注入的
*/
Object shortcut = descriptor.resolveShortcut(this);
//如果找到了依赖,直接返回,一般都是null
if (shortcut != null) {
return shortcut;
}
/*
* 获取descriptor包装的依赖的类型
*/
Class<?> type = descriptor.getDependencyType();
/*
* 2 尝试获取@Value注解的值进行注入,QualifierAnnotationAutowireCandidateResolver的方法
*
* 获取autowireCandidateResolver,默认是SimpleAutowireCandidateResolver类型的实例,那么该方法固定返回null,如果开启了注解支持
* 那么在前面讲的registerAnnotationConfigProcessors方法中会默认注入的是一个ContextAnnotationAutowireCandidateResolver实例
* 最后是调用父类QualifierAnnotationAutowireCandidateResolver的getSuggestedValue方法实现
* QualifierAnnotationAutowireCandidateResolver主要处理@Qualifier、@Value以及JSR-330的javax.inject.Qualifier注解
*
* 这里的getSuggestedValue方法就是处理@Value注解,读取 @Value 对应的值(如果存在),用于后续进行依赖注入,没有就返回null
*/
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
//如果value不为null,说明存在@Value注解,并且获取到了值
if (value != null) {
//如果属于String
if (value instanceof String) {
/*
* 这里就是解析value值中的占位符的逻辑,将占位符替换为属性值,关键方法就是resolveStringValue
* 因此@Value支持占位符,即${.. : ..},占位符的语法和解析之前就学过了,这里的占位符支持普通方式从外部配置文件中加载进来的属性以及environment的属性。
*/
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
/*
* 这里就是解析value值中的SPEL表达式的逻辑,将SPEL表达式解析为指定值
*
* 使用默认StandardBeanExpressionResolver(在prepareBeanFactory方法中注册的)解析value值中SPEL表达式
* 因此@Value支持SPEL表达式,即#{},SPEL表达式的语法之前就学过了
*
*/
value = evaluateBeanDefinitionString(strVal, bd);
}
//获取类型装换器,做类型转换处理
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
//尝试将解析后的value值转换为依赖项的类型,并返回
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
} catch (UnsupportedOperationException ex) {
//如果转换失败,使用不支持类型描述器分辨率的自定义类型转换器转换并返回
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
/*
* 3 尝试解析集合依赖:Stream、Array、Collection、Map
* Spring会将符合条件的bean都注入到集合中
*/
//解析集合依赖,返回的就是所需的依赖参数
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
//如果找到了依赖,那么直接返回,没找到,那么继续下一步
if (multipleBeans != null) {
return multipleBeans;
}
/*
* 4 尝试解析普通单个依赖
*/
//容器中根据type(类型)查找满足条件的候选beanName及其对应的的实例或者Class对象映射map,返回一个Map
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
/*如果是空集合*/
if (matchingBeans.isEmpty()) {
//通过isRequired判断该依赖项是否是必须的,可通过@Autowired(required = false)设置为非必须依赖
if (isRequired(descriptor)) {
//对于无法解析(没找到)的依赖,引发NoSuchBeanDefinitionException 或者 BeanNotOfRequiredTypeException异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
//返回null
return null;
}
/*
* 到这里,表示找到了依赖,如果有多个依赖那么需要选择某个
*/
//最终依赖beanName
String autowiredBeanName;
//最终依赖的实例或者Class
Object instanceCandidate;
/*如果候选依赖大于一个*/
if (matchingBeans.size() > 1) {
//@Primary、@Priority、resolvableDependencies缓存、banName顺序依次解析
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
//如果autowiredBeanName为null,表示没找到
if (autowiredBeanName == null) {
//如果该依赖是必须的,或者不是集合依赖(如果是Collection还必须是接口)
//将在resolveNotUnique方法中抛出NoUniqueBeanDefinitionException异常
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
//如果不是必须的,或者是符合条件的集合依赖,将返回null,即最终注入空集合,不会抛出异常
else {
return null;
}
}
//获取候选依赖value,可能是实例或者class
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
/*如果候选依赖只有一个,那么该候选依赖为最终依赖*/
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
//如果autowiredBeanNames不为null,那么将最后候选依赖名字加入自动注入的beanName的集合
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//如果instanceCandidate属于Class,那么反射实例化
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
//最终结果result,该结果就是要注入的依赖项的实例
Object result = instanceCandidate;
//如果是NullBean,表示没有从容器中获取到的实例为null
if (result instanceof NullBean) {
//如果该依赖项是必须的,那么抛出NoSuchBeanDefinitionException或者BeanNotOfRequiredTypeException异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
//如果不是必须的,那么返回null
result = null;
}
//如果result不属于依赖的类型,抛出BeanNotOfRequiredTypeException异常
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
//返回result,依赖项查找完毕
return result;
} finally {
//无论是正常返回还是抛出异常都会走该逻辑,将注入点修改为原来的注入点
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
getSuggestedValue用于判断给定的依赖项是否存在@Value注解,并且尝试获取@Value注解的值,如果没有@Value注解就返回null。
/**
* QualifierAnnotationAutowireCandidateResolver的方法
*
* 确定给定的依赖项是否声明@Value注解,并且获取注解的值
*/
@Override
@Nullable
public Object getSuggestedValue(DependencyDescriptor descriptor) {
//获取descriptor中包装的字段,或者方法/构造器的对应参数上关联的注解,并查找@Value注解获取值
Object value = findValue(descriptor.getAnnotations());
if (value == null) {
//获取descriptor中包装的方法/构造器参数
MethodParameter methodParam = descriptor.getMethodParameter();
//如果不为null,说明确实是包装的一个方法/构造器参数
if (methodParam != null) {
//那么获取该参数对应的方法/构造器上的注解,并查找@Value注解获取值
value = findValue(methodParam.getMethodAnnotations());
}
}
return value;
}
/**
* QualifierAnnotationAutowireCandidateResolver的属性
*
* Value注解的class
*/
private Class<? extends Annotation> valueAnnotationType = Value.class;
/**
* QualifierAnnotationAutowireCandidateResolver的方法
*
* 尝试从一批注解中获取@Value注解的值
*/
@Nullable
protected Object findValue(Annotation[] annotationsToSearch) {
//如果存在注解
if (annotationsToSearch.length > 0) {
//返回一个包含Value类型的注解的全部属性的映射实例
AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
//如果不为null,说明存在@Value注解
if (attr != null) {
//那么提取value属性的值
return extractValue(attr);
}
}
//没有@Value注解就返回null
return null;
}
/**
* QualifierAnnotationAutowireCandidateResolver的方法
*
* 从给定的注解中提取value属性值
*/
protected Object extractValue(AnnotationAttributes attr) {
Object value = attr.get(AnnotationUtils.VALUE);
//如果值为null,那么抛出异常
if (value == null) {
throw new IllegalStateException("Value annotation must have a value attribute");
}
return value;
}
如果是Stream、Array、Collection(还必须是接口)、Map等集合类型,则会调用resolveMultipleBeans方法解析集合依赖,返回的候选依赖集合将会全部注入到属性中,因此返回的集合中的value全部是bean实例。
/**
1. DefaultListableBeanFactory的方法
2.
3. 解析集合依赖,将会查找所有符合条件的bean注入到集合中
4. 5. @param descriptor 即将注入的特定依赖项的描述符,包含MethodParameter或者Filed的信息
6. @param beanName beanName
7. @param autowiredBeanNames 自动注入的beanName的集合
8. @param typeConverter 类型转换器
9. @return 对应类型的集合,没找到就返回null
*/
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
//获取依赖类型
Class<?> type = descriptor.getDependencyType();
/*
* 1 Stream处理
* 如果descriptor属于StreamDependencyDescriptor,这是用于Stream流访问多个元素的依赖项描述符标记
* 一般都是DependencyDescriptor类型,在resolveStream方法中会使用StreamDependencyDescriptor类型
*
* 通过findAutowireCandidates查找符合条件的bean集合,最终将会返回一个Stream,包含了全部找到的bean实例
*/
if (descriptor instanceof StreamDependencyDescriptor) {
//容器中根据type查找满足条件的候选bean名称和候选bean实例的映射map,返回一个Map
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//加入到autowiredBeanNames集合中
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
.map(name -> descriptor.resolveCandidate(name, type, this))
.filter(bean -> !(bean instanceof NullBean));
//通过dependencyComparator比较器排序,也就是按照Order排序,之前讲过了
//dependencyComparator默认是null,也就是不排序,除非手动设置或者开启注解支持
//开启注解支持时将会在registerAnnotationConfigProcessors方法中注入AnnotationAwareOrderComparator比较器,支持注解排序
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;
}
/*
* 2 Array处理
*
* 通过findAutowireCandidates查找符合条件的bean集合,最终将会返回一个Array,包含了全部找到的bean实例
*/
else if (type.isArray()) {
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve(type);
if (resolvedArrayType != type) {
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
//容器中根据type查找满足条件的候选bean名称和候选bean实例的映射map,返回一个Map
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
//加入到autowiredBeanNames集合中
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
//map的value转换类型
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
//通过dependencyComparator比较器排序,也就是按照Order排序,之前讲过了
//dependencyComparator默认是null,也就是不排序,除非手动设置或者开启注解支持
//开启注解支持时将会在registerAnnotationConfigProcessors方法中注入AnnotationAwareOrderComparator比较器,支持注解排序
if (result instanceof Object[]) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
Arrays.sort((Object[]) result, comparator);
}
}
return result;
}
/*
* 3 Collection处理
*
* 通过findAutowireCandidates查找符合条件的bean集合,最终将会返回一个对应类型的集合,包含了全部找到的bean实例
* 注意Collection类型还必须是接口
*/
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
//Collection元素泛型类型
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
//容器中根据type查找满足条件的候选bean名称和候选bean实例的映射map,返回一个Map
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
//加入到autowiredBeanNames集合中
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
//map的value转换类型
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
//通过dependencyComparator比较器排序,也就是按照Order排序,之前讲过了
//dependencyComparator默认是null,也就是不排序,除非手动设置或者开启注解支持
//开启注解支持时将会在registerAnnotationConfigProcessors方法中注入AnnotationAwareOrderComparator比较器,支持注解排序
if (result instanceof List) {
if (((List<?>) result).size() > 1) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
}
return result;
}
/*
* 4 Map处理
*
* 通过findAutowireCandidates查找符合条件的bean集合,最终将会返回一个Map,包含了全部找到的bean实例
*/
else if (Map.class == type) {
//Map元素泛型类型
ResolvableType mapType = descriptor.getResolvableType().asMap();
//key类型
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
//value类型
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
//容器中根据type查找满足条件的候选bean名称和候选bean实例的映射map,返回一个Map
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
//加入到autowiredBeanNames集合中
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
//直接将查找到的map返回
return matchingBeans;
} else {
return null;
}
}
核心方法。查找与所需类型匹配的 bean 实例,将会返回匹配的所需类型的候选bean名称和候选bean实例或者Class的映射map,永远不会为null。
/**
* DefaultListableBeanFactory的方法
*
* 查找与所需类型匹配的 bean 实例。 在指定 bean 的自动装配期间调用。
*
* @param beanName 将装配的beanName
* @param requiredType 要查找的 bean 的实际类型(可能是数组或集合元素类型)
* @param descriptor 要解析的依赖项的描述符
* @return 匹配的所需类型的候选bean名称和候选bean实例或者Class的映射map,永远不会为null
*/
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//获取从所有缓存中给定类型的所有 bean 名称,排除别名,包括在祖先工厂中定义的 bean 名称,
//包括其他类型的bean(比如原型bean),包括FactoryBean返回的实例类型以及FactoryBean本省,包括工厂方法返回的类型
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
//新建一个LinkedHashMap用于存放要返回的结果
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
//遍历resolvableDependencies缓存映射,前面学习的prepareBeanFactory方法中,我们就知道Spring会预先存放四个预定义类型以及实现到该缓存中
//这个缓存用于存放已经解析的依赖项到相应的自动注入的实例的map,这里就使用到了
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
//获取注入类型
Class<?> autowiringType = classObjectEntry.getKey();
//如果该类型匹配或兼容当前所需依赖类型
if (autowiringType.isAssignableFrom(requiredType)) {
//获取注入的实例
Object autowiringValue = classObjectEntry.getValue();
//根据给定的所需类型解析给定的自动装配值
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
//如果当前实例属于requiredType类型
if (requiredType.isInstance(autowiringValue)) {
//那么加入结果集,跳出循环
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
/*
* 遍历找到的beanName集合,进一步筛选有资格的bean
*/
for (String candidate : candidateNames) {
//判断是否不是自引用,以及给定的beanName对应的bean定义是否有资格作为候选bean被自动注入到其他bean中,即XML的autowire-candidate属性
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
//如果有资格,那么将候选beanName及其对应的的实例或者Class对象添加到result中
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
/*
* 如果结果集为空集,那么可能会放宽条件尽量匹配
*/
if (result.isEmpty()) {
//是否是所需类型是否是集合类型(如果是Collection还必须是接口)
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
//降级匹配,比如强制转型
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
//如果是空集并且不是集合类型,那么尝试自引用匹配
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
获取给定类型的所有 bean 名称,包括在祖先工厂中定义的 bean 名称。将返回唯一名称,以防被覆盖的 bean 定义。
将会查找所有类型的bean定义,以及工厂方法返回的类型,以及FactoryBean创建的对象类型,以及FactoryBean本身的类型。因此将可能初始化lazy-init,以及FactoryBean实例及其返回对象,以及工厂方法的返回对象。
/**
* BeanFactoryUtils的方法
*
* 获取给定类型的所有 bean 名称,包括在祖先工厂中定义的 bean 名称。将返回唯一名称,以防被覆盖的 bean 定义。
* 如果设置了allowEagerInit标志为true,则考虑FactoryBean创建的对象,这意味着FactoryBean将被初始化。
* 如果FactoryBean创建的对象不匹配,则原始FactoryBean本身将根据类型进行匹配。
* 如果没有设置allowEagerInit,将只检查原始的FactoryBean(这不需要初始化每个FactoryBean)。
*
* @param lbf bean factory
* @param includeNonSingletons 是否也包括其他类型bean(包括FactoryBeans)
* @param allowEagerInit 是否初始化lazy-init单例以及FactoryBean创建的实例以及factory-bean工厂方法返回的单例来进行类型检查。
* 请注意,工厂Bean需要急切地初始化以确定其类型:因此传递此标志为true将初始化FactoryBean和"factory-bean"引用。
* @param type bean必须匹配的类型
* @return 匹配的 bean 名称的数组,或空数组(如果没有匹配到任何一个)
*/
public static String[] beanNamesForTypeIncludingAncestors(
ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
Assert.notNull(lbf, "ListableBeanFactory must not be null");
//调用getBeanNamesForType查找匹配给定类型的beanName
String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
if (lbf instanceof HierarchicalBeanFactory) {
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
//递归调用该方法,从父工厂中查找匹配给定类型的beanName
String[] parentResult = beanNamesForTypeIncludingAncestors(
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
//将给定的 bean 名称结果与给定的从父工厂获取的 bean 名称结果合并
//合并规则是:包括所有本地 bean 名称结果 + 本地结果不包含并且本地 bean factory中不包含的该名称bean实例或bean定义的 父 bean 名称结果
result = mergeNamesWithParent(result, parentResult, hbf);
}
}
return result;
}
核心方法就是getBeanNamesForType,该方法也是DefaultListableBeanFactory实现的方法。
返回与给定类型匹配(包括子类)的bean的名称,还可以尝试从allBeanNamesByType或者singletonBeanNamesByType缓存中查找,如果缓存中没有,那么从将会从所有注册的beanName缓存(包括自动注册的以及手动注册的)中查找(不包括别名)。
/**
* DefaultListableBeanFactory的方法
*
* 返回与给定类型匹配的bean的名称(包括子类),还可以从bean定义或者FactoryBeans下的getObjectType的返回值来判断。
*
* @param type 要匹配的类或接口,或所有bean名称的(传递null)
* @param includeNonSingletons 是包含原型bean以及其他返回范围bean,还是只包含单例bean(也适用于FactoryBeans)
* @param allowEagerInit 是否初始化lazy-init单例以及FactoryBean创建的实例以及factory-bean工厂方法返回的单例来进行类型检查。
* 请注意,工厂Bean需要急切地初始化以确定其类型:因此传递此标志为true将初始化FactoryBean和"factory-bean"引用。
* bean必须匹配的类型
* @return 与给定类型匹配的bean的名称(包括子类)数组
*/
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
//isConfigurationFrozen:如果没有冻结bean定义,在finishBeanFactoryInitialization方法中就被设置为true了
//如果type类型为null或者不允许急切初始化,直接主动查找
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
//根据includeNonSingletons尝试从allBeanNamesByType或者singletonBeanNamesByType缓存中获取
//这两个缓存我们前面就见过,折现我们可以知道他们的作用就是方法精心干类型查找beanName
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
//根据类型返回匹配的resolvedBeanNames数组
String[] resolvedBeanNames = cache.get(type);
//不为null就返回找到的数组
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
//缓存没找到就主动查找
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
//将结果放入缓存
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
/**
* DefaultListableBeanFactory的方法
*
* 将会从所有注册的beanName缓存(包括自动注册的以及好手动注册的)中查找(不包括别名),返回与给定类型匹配(包括子类)的bean的名称
* 支持匹配
*
* @param type 要匹配的类或接口,或所有bean名称的(传递null)
* @param includeNonSingletons 是包含原型bean以及其他返回范围bean,还是只包含单例bean(也适用于FactoryBeans)
* @param allowEagerInit 是否初始化lazy-init单例以及FactoryBean创建的实例以及factory-bean工厂方法返回的单例来进行类型检查。
* 请注意,工厂Bean需要急切地初始化以确定其类型:因此传递此标志为true将初始化FactoryBean和"factory-bean"引用。
* bean必须匹配的类型
* @return 与给定类型匹配的bean的名称(包括子类)数组
*/
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();
/*
* 1 检查所有beanDefinitionNames的缓存
*
*/
for (String beanName : this.beanDefinitionNames) {
//之地不是别名的beanName进行操作
if (!isAlias(beanName)) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查符合规则的 bean 定义:
//不是抽象的,并且(允许急切初始化,或者(指定class或者不是lazy-init或者允许工厂急切地加载 bean 实例),并且不需要快速初始化以确定其类型)
if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
//是否是FactoryBean
boolean isFactoryBean = isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
boolean matchFound = false;
//是否允许FactoryBean初始化
boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
//bean定义是否不是lazy-init
boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
/*非FactoryBean*/
if (!isFactoryBean) {
//如果包含其它类型的bean,或者是单例的
if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
//判断类型是否匹配
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
/*FactoryBean*/
else {
//如果包含其它类型的bean,或者不是lazy-init,或者(允许FactoryBean初始化并且是单例的)
if (includeNonSingletons || isNonLazyDecorated ||
(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
//判断类型是否匹配
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
//如果没有匹配,检查FactoryBean本身
if (!matchFound) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
//如果匹配,那么加入结果集合
if (matchFound) {
result.add(beanName);
}
}
} catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably a placeholder: let's ignore it for type matching purposes.
LogMessage message = (ex instanceof CannotLoadBeanClassException ?
LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));
logger.trace(message, ex);
// Register exception, in case the bean was accidentally unresolvable.
onSuppressedException(ex);
} catch (NoSuchBeanDefinitionException ex) {
// Bean definition got removed while we were iterating -> ignore.
}
}
}
/*
* 2 检查所有手动注册的单例
*/
for (String beanName : this.manualSingletonNames) {
try {
// 在属于FactoryBean的情况下,匹配由FactoryBean创建的对象。
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
// Match found for this bean: do not match FactoryBean itself anymore.
continue;
}
// In case of FactoryBean, try to match FactoryBean itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
//匹配原始 bean 实例(可能是原始FactoryBean)
// Match raw bean instance (might be raw FactoryBean).
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
} catch (NoSuchBeanDefinitionException ex) {
// Shouldn't happen - probably a result of circular reference resolution...
logger.trace(LogMessage.format(
"Failed to check manually registered singleton with name '%s'", beanName), ex);
}
}
return StringUtils.toStringArray(result);
}
在确定候选依赖beanName满足条件之后,则尝试将候选依赖beanName及其对应的bean实例或者Class存入要返回的映射map集合。
1 如果是集合类型依赖,因为返回的集合中的依赖项会全部注入,因此所有的候选依赖都会调用getBean实例化。
2 如果是普通类型依赖项,且已被实例化了,那么返回实例;如果没有被实例化,那么就返回对应的候选依赖的Class,因为最终只会选择一个合适的依赖项,其他不合适的依赖项没必要初始化!
/**
1. DefaultListableBeanFactory的方法
2.
3. 如果有资格(beanName校验通过),那么将候选beanName及其对应的的实例或者Class对象添加到result中
4. 5. @param candidates 要返回的候选beanName及其对应的的实例或者Class对象映射map
6. @param candidateName 找到的beanName
7. @param requiredType 要查找的 bean 的实际类型(可能是数组或集合元素类型)
8. @param descriptor 要解析的依赖项的描述符
*/
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
/*如果是集合类型描述符,在resolveMultipleBeans方法中会使用集合描述符*/
if (descriptor instanceof MultiElementDescriptor) {
//获取bean实例,实际上就是调用beanFactory.getBean(beanName)方法,因此可能会触发bean实例化
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
//如果不是NullBean,即返回的不是null
if (!(beanInstance instanceof NullBean)) {
//将实例加入映射中
candidates.put(candidateName, beanInstance);
}
}
/*否则,如果已初始化该beanName的单例实例,或者是Stream类型描述符*/
else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
((StreamDependencyDescriptor) descriptor).isOrdered())) {
//获取bean实例,实际上就是调用beanFactory.getBean(beanName)方法,因此可能会触发bean实例化
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
//将实例加入映射中,如果是NullBean则加入null
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
/*否则,直接将找到的beanName所属的Class加入map映射*/
else {
candidates.put(candidateName, getType(candidateName));
}
}
如果依赖项类型不是集合类型,并且存在多余一个候选依赖注入项,那么调用determineAutowireCandidate方法确定给定候选依赖集合中的最合适的一个候选依赖名称。
将会按照@Primary注解标注的类或者primary=true属性标注的bean定义 -> @Primary注解标注的类或者primary=true属性标注的bean定义 -> resolvableDependencies缓存 -> banName (注意byType的setter自动注入不会匹配beanName)的顺序依次解析:
/**
* DefaultListableBeanFactory的方法
*
* 确定给定 bean 集合中的候选依赖名称。按照@Primary、@Priority、resolvableDependencies缓存、banName顺序依次解析
*
* @param candidates 与所需类型匹配的候选beanName和bean实例的映射map,通过前面的findAutowireCandidates方法调用返回的
* @param descriptor 要匹配的目标依赖项描述符
* @return 找到的候选项的名称,如果未找到则返回null
*/
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
//获取依赖类型
Class<?> requiredType = descriptor.getDependencyType();
/*
* 1 根据@Primary注解标注的类或者primary=true属性标注的bean定义,获取主侯选依赖的beanName
* @Primary注解的解析需要开启注解解析支持
* 如果候选依赖中存在多个主候选依赖则抛出异常:more than one 'primary' bean found among candidates……
*
*/
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
//如果不为null,那么直接返回主候选依赖beanName
if (primaryCandidate != null) {
return primaryCandidate;
}
/*
* 2 根据@Priority注解标注的类比较优先级,获取侯选依赖的beanName,优先级值越小那么优先级越高。注意@Order注解不起作用
* @Priority注解的解析需要AnnotationAwareOrderComparator(开启注解解析支持),默认OrderComparator只会返回null
* 如果候选依赖中存在多个候选依赖存在相同的优先级则抛出异常:Multiple beans found with the same priority……
*/
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
//如果不为null,那么直接返回优先级最高的候选依赖beanName
if (priorityCandidate != null) {
return priorityCandidate;
}
/*
* 3 上面都不找不到合适的候选依赖。最后,使用默认策略
*
* 3.1 如果resolvableDependencies中已经注册了该候选依赖的依赖关系,则返回该候选依赖的beanName
* 3.2 如果需要的注入的属性的名称与某个候选依赖的beanName或者某个别名相同,则返回该候选依赖的beanName
*/
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
//1 首先,如果resolvableDependencies中已经注册了该候选依赖的依赖关系,那么使用直接使用该候选依赖的beanName
//2 其次,如果需要的注入的属性的名称与某个候选依赖的beanName或者别名相同,则返回该候选依赖的beanName
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
//返回该beanName
return candidateName;
}
}
//找不到就返回null
return null;
}
determineAutowireCandidate方法的第一个尝试匹配逻辑。@Primary注解和primary=true属性我们在IoC学习部分就讲过了,这里的就是它的解析源码。
根据@Primary注解标注的类或者primary=true属性标注的bean定义,获取主侯选依赖的beanName。对于@Primary注解的解析则需要开启注解解析支持。如果候选依赖集合中存在多个主候选依赖则抛出异常:more than one ‘primary’ bean found among candidates……。找到就返回,找不到则继续向下查找。
/**
* DefaultListableBeanFactory的方法
*
* 确定给定 bean 集合中的主要候选依赖,即@Primary注解标注的类或者primary=true属性标注的bean定义
* 如果候选依赖中存在多个主候选依赖则抛出异常:more than one 'primary' bean found among candidates
*
* @param candidates 匹配所需类型的候选名称和候选实例或者Class的map
* @param requiredType 要匹配的目标依赖项类型
* @return 主候选项的名称,如果未找到返回null
*/
@Nullable
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
//保存主候选项的名称,同时用于校验唯一性
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
//当前依赖是否被设置为主要候选依赖,即@Primary注解标注的类或者primary=true属性标注的bean定义
if (isPrimary(candidateBeanName, beanInstance)) {
//如果主候选依赖不为null,这说明存在多个主侯选依赖
if (primaryBeanName != null) {
//当前beanFactory是否包含当前candidateBeanName的bean定义
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
//当前beanFactory是否包含当前primaryBeanName的bean定义
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
//如果都满足,那么抛出异常
//即如果候选依赖中存在多个主候选依赖则抛出异常:more than one 'primary' bean found among candidates
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
/*
* 否则,如果candidateLocal为true,primaryLocal为false,这说明当前candidateBeanName的bean定义在当前beanFactory中
* 而原来的primaryBeanName的bean定义在父beanFactory中,则将原来的primaryBeanName替换为当前candidateBeanName
* 这说明子beanFactory的主候选依赖优先级高于父beanFactory的主候选依赖
*/
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
//如果主候选依赖为null,那么primaryBeanName设置为当前candidateBeanName
else {
primaryBeanName = candidateBeanName;
}
}
}
//返回唯一的主候选依赖的beanName
return primaryBeanName;
}
determineAutowireCandidate方法的第二个尝试逻辑。@Priority注解我们在IoC学习部分就讲过了,这里的就是它的解析源码。
根据@javax.annotation.Priority注解确定给定 bean 集合中的优先级最高的候选依赖。根据Ordered接口的定义,值越小,优先级越高。注意@Order注解不起作用,@Priority注解的解析需要AnnotationAwareOrderComparator(同样是开启注解解析支持),默认只会返回null。
如果候选依赖中存在多个候选依赖具有相同的优先级则抛出异常:Multiple beans found with the same priority……。找到就返回,找不到则继续向下查找。
/**
1. DefaultListableBeanFactory的方法
2.
3. 根据@javax.annotation.Priority注解确定给定 bean 集合中的优先级最高的候选依赖。根据Ordered接口的定义,值越小,优先级越高
4. 注意@Order注解不起作用,@Priority注解的解析需要AnnotationAwareOrderComparator(同样是开启注解解析支持),默认OrderComparator只会返回null。
5. 如果候选依赖中存在多个候选依赖具有相同的优先级则抛出异常:Multiple beans found with the same priority……。找到就返回,找不到则继续向下查找。
6. 7. @param candidates 匹配所需类型的候选名称和候选实例或者Class的map
8. @param requiredType 要匹配的目标依赖项类型
9. @return 主候选项的名称,如果未找到返回null
*/
@Nullable
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
//最高优先级的beanName
String highestPriorityBeanName = null;
//最高优先级值
Integer highestPriority = null;
/*遍历candidates映射,查找最高优先级的beanName*/
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance != null) {
//通过dependencyComparator获取@javax.annotation.Priority注解的值,dependencyComparator默认为null因此返回null
//开启注解支持之后会使用设置为AnnotationAwareOrderComparator,那里面能够解析@javax.annotation.Priority注解
Integer candidatePriority = getPriority(beanInstance);
//如果candidatePriority不为null,即设置了@javax.annotation.Priority注解
if (candidatePriority != null) {
//如果highestPriorityBeanName不为null
if (highestPriorityBeanName != null) {
//如果两个优先级相等,那么抛出异常:Multiple beans found with the same priority
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
//如果当前优先级数值更小,那么级别更高,替换为当前的依赖项的beanName以及优先级
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
//如果highestPriorityBeanName为null,说明是第一次设置,那么直接设置为当前的依赖项的beanName以及优先级
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
}
//返回最高优先级的beanName
return highestPriorityBeanName;
}
在解析构造器和参数成功之后,会将已解析的构造器和参数存入缓存,storeCache是ArgumentsHolder的方法。
/**
* ArgumentsHolder的方法
*
* 解析的构造器和参数存入缓存
*
* @param mbd bean定义
* @param constructorOrFactoryMethod 解析的构造器或者工厂方法
*/
public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
//将当前mbd的的resolvedConstructorOrFactoryMethod设置为当前已解析的构造器或工厂方法
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
//将当前mbd的的constructorArgumentsResolved设置为true
mbd.constructorArgumentsResolved = true;
//preparedConstructorArguments和resolvedConstructorArguments这两个缓存只存在一个
//如果参数需要解析
if (this.resolveNecessary) {
//将当前mbd的的preparedConstructorArguments设置为找到的preparedArguments
mbd.preparedConstructorArguments = this.preparedArguments;
}
//如果不需要解析
else {
//将当前mbd的的resolvedConstructorArguments设置为找到的arguments
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
在找到构造器以及解析参数完毕之后,就会调用instantiate方法,传递beanName、mbd、uniqueCandidate、EMPTY_ARGS初始化bean实例,随后设置到bw的相关属性中。
实际上除了查找方法注入会返回CGLIB代理之外,其他情况下最终都是调用BeanUtils工具类的instantiateClass方法,传递构造器和参数就行了。BeanUtils是Spring的工具类,我们自己也能使用,可以进行实例化bean、拷贝bean属性的操作,估计应该有人用过。最终就是就是反射调用构造器,并且为构造器参数赋值,并创建一个bean实例返回,还是很简单的。
/**
* ConstructorResolver的方法
*
* 通过构构造器与参数创建bean实例
*
* @param beanName beanName
* @param mbd 已合并的RootBeanDefinition
* @param constructorToUse 被选中的构造器
* @param argsToUse 构造器参数数组
* @return bean实例
*/
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
//获取bean实例化策略对象strategy,默认使用SimpleInstantiationStrategy实例
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
//安全管理器相关,不需要关系一般不会走这条路径
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
} else {
//委托strategy对象的instantiate方法创建bean实例
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
/**
* SimpleInstantiationStrategy的方法
*
* @param bd bean定义
* @param beanName beanName
* @param owner 当前beanFactory
* @param ctor 构造器
* @param args 构造器参数
* @return
*/
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
/*
* hasMethodOverrides判断当前bean定义是否设置了查找方法,即是否设置了、标签
* 一般都是没有设置的,因此走第一个逻辑
*/
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
/*
* 到这一步,我们发现,实际上就是调用的BeanUtils工具类的instantiateClass方法,传递构造器和参数就行了
* BeanUtils是Spring的工具类,我们自己也能使用,可以进行实例化bean、拷贝bean属性的操作,估计应该有人用过
*
* 这一步就是反射调用构造器,并且为构造器参数赋值,并创建一个bean实例返回,还是很简单的
*/
return BeanUtils.instantiateClass(ctor, args);
}
/*
* 如果设置了、查找方法注入,那么需要使用CGLIB实现子类,
* 返回的是代理对象,很少用到,目前不必关心
*/
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
/**
* AbstractAutowireCapableBeanFactory的方法
*
* 使用其默认无参构造器实例化给定 bean
*
* @param beanName beanName
* @param mbd bean的BeanDefinition
* @return 新实例的 Beanwrapper
*/
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
//如果存在安全管理器,一般不存在
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
} else {
//通用逻辑
//getInstantiationStrategy,返回用于创建 bean 实例的实例化策略,就是instantiationStrategy属性
//默认是CglibSubclassingInstantiationStrategy类型的实例,实现了SimpleInstantiationStrategy
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
//新建BeanWrapperImpl,设置到内部属性中
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
//初始化BeanWrapper,此前讲过了
//主要是为当前的BeanWrapperImpl实例设置转换服务ConversionService以及注册自定义的属性编辑器PropertyEditor。
initBeanWrapper(bw);
return bw;
} catch (Throwable ex) {
//抛出异常
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
/**
1. SimpleInstantiationStrategy的方法
2.
3. 返回此工厂中具有给定名称的 bean 实例
4. 5. @param bd bean的BeanDefinition
6. @param beanName beanName
7. @param owner beanFactory
8. @return bean实例
*/
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
/*
* hasMethodOverrides判断当前bean定义是否设置了查找方法,即是否设置了、标签
* 一般都是没有设置的,因此走第一个逻辑
*/
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
//获取resolvedConstructorOrFactoryMethod缓存属性
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
//如果缓存的构造器不为null,表示此前解析过
if (constructorToUse == null) {
//返回 bean 定义的指定类型
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) {
//抛出No default constructor found
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
/*
* 到这一步,我们发现,实际上就是调用的BeanUtils工具类的instantiateClass方法,传递构造器就行了
* BeanUtils是Spring的工具类,我们自己也能使用,可以进行实例化bean、拷贝bean属性的操作,估计应该有人用过
*
* 这一步就是反射调用构造器,并创建一个bean实例返回,还是很简单的
*/
return BeanUtils.instantiateClass(constructorToUse);
}
/*
* 如果设置了、查找方法注入,那么需要使用CGLIB实现子类,
* 返回的是代理对象,很少用到,目前不必关心
*/
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
本次主要接着上一篇文章,继续讲解finishBeanFactoryInitialization方法的源码解析,主要就是获取bean实例的过程,以及构造器依赖注入的过程,核心知识点包括:
createBeanInstance
方法,doCreateBean方法中的核心方法之一。将会使用使用适当的实例化策略创建Bean实例,并返回包装类BeanWrapper。采用的策略有:工厂方法实例化、自动注入带参数构造器实例化或默认无参构造器简单实例化。本篇文章实际上主要就是讲解的createBeanInstance方法。determineConstructorsFromBeanPostProcessors
方法,位于createBeanInstance方法中。回调所有SmartInstantiationAwareBeanPostProcessor类型后处理器的determineCandidateConstructors方法,用于确定候选构造器数组。这一步的主要实现就是AutowiredAnnotationBeanPostProcessor后处理器,这个处理器是通过< component-scan/>标签添加的,它通过解析构造器上的@Autowired、@Inject注解以及一些规定来确定候选构造器数组。可以说该方法主要是用于支持注解的自动注入!autowireConstructor
方法,位于createBeanInstance方法中。这是通过构造器自动注入初始化bean实例的核心方法 。如果determineConstructorsFromBeanPostProcessors方法找到的候选构造器数组不为null(开起了注解支持),或者自动注入模式为构造器自动注入(这是XML设置的自动注入模式),或者XML对应的bean定义定义了< constructor-arg/>标签,或者外部设置的参数数组args不为空,那么都会调用该方法。instantiateBean
方法,位于createBeanInstance方法中。默认通过无参构造器初始化bean实例。 当上面的条件不满足时,就会调用该方法,默认会直接使用无参构造器创建实例。在大量使用注解的今天,一般都是通过无参构造器创建对象的,还能避免构造器的循环依赖,但仍然不是通过该方法初始化的,而是通过autowireConstructor方法调用无参构造器初始化的,因为开启了注解支持,determineConstructorsFromBeanPostProcessors方法会返回一个无参构造器而不是null。如果采用了无参构造器初始化,那么依赖在哪里注入的呢?自然是通过createBeanInstance方法的后续方法完成的,后面会讲,比如方法注入、属性反射注入……。BeanWrapper
体系,这是Spring实例化bean过程中的一个重要接口体系,它内部包含了被封装后待处理的bean实例和用于设置bean属性的属性编辑器,主要用于后续对bean实例进行属性装配(填充),用在populateBean方法中。后面的文章会讲解populateBean方法。BeanWrapper一般都是Spring IoC内部使用的,开发人员用不到。resolveConstructorArguments
方法,位于autowireConstructor方法中。该方法用于解析XML的bean定义中的手动设置的构造器参数,实际上就是解析< constructor-arg/>子标签的值,并返回构造器参数的数量,默认就是< constructor-arg/>子标签的数量。 因此对于基于注解的配置来说将返回0,并且不会解析任何手动设置的构造器参数。类似于determineConstructorsFromBeanPostProcessors方法用于支持注解配置,该方法可以说专门用于支持XML的配置。createArgumentArray
方法,位于autowireConstructor方法中。通过给定的构造器以及此前的resolveConstructorArguments方法已解析的构造器参数值以及参数名和类型等参数尝试创建属于该构造器的参数值数组,用于后面反射调用构造器或工厂方法,返回一个参数值数组持有者。 ArgumentsHolder。resolveAutowiredArgument
方法,位于createArgumentArray方法中。 如果在此前解析的XML配置的属性值中没找到匹配参数的值,并且支持自动注入(候选构造器数组不为null,或者XML配置的自动注入的模式为AUTOWIRE_CONSTRUCTOR,即构造器注入),那么会调用该方法。该方法会到整个容器中去查找,将会返回找到的满足条件的bean实例,这一步将可能触发其他bean定义的初始化,这是构造器自动装配核心方法。resolveDependency
方法,位于resolveAutowiredArgument方法中。 根据此工厂中的 bean定义解析指定的依赖项,简单的说就是从容器中查找符合的bean实例并返回,找不到就可能会抛出异常。getLazyResolutionProxyIfNecessary
方法,位于resolveDependency方法中。 如果该依赖项本身或者所属的构造器/方法上标注了@Lazy注解,那么调用该方法返回一个代理对象,将根据依赖的类型自动选择走JDK动态代理还是CGLIB代理。该方法还用于手动解决构造器循环依赖注入,依靠的就是@Lazy注解。doResolveDependency
方法,位于resolveAutowiredArgument
方法中。真正的从此工厂中的 bean查找符合条件的依赖项并获取对应的bean实例返回的方法,因此可能会触发其他依赖的项bean的实例化。很多的自动注入模式都调用了该方法,除了本文讲的基于XML和注解配置的构造器自动注入之外,包括后面我们会讲到的@Autowired注解的setter方法注入、属性反射注入,XML配置的基于byType的setter方法自动注入(直接调用外层resolveDependency方法,并且不会走最后的banName查找),@Resource注解的后续byType注入(直接调用外层resolveDependency方法)等等注入逻辑内部也都会调用该方法。而其他的自动注入模式,比如XML配置的基于byName的setter方法自动注入则有自己的逻辑!本文主要讲解了创建bean实例的createBean方法的整体流程,知道了核心方法是doCreateBean方法,随后还详细解析了doCreateBean方法内部的第一个核心方法createBeanInstance的源码,createBeanInstance方法用于选择合适的构造器创建bean实例以及进行基于XML或者注解的构造器自动注入,实际上这一部分源码被称为bean的“实例化”。
在后面的文章中,我们继续分析doCreateBean方法的后续源码,后面的源码则被称为为bean的“初始化”的过程。如果bean的“初始化”分析完毕,那么整个IoC容器初始化的大概流程也就分析的差不多了,bean的“初始化”核心过程包括:
相关文章:
https://spring.io/
Spring 5.x 学习
Spring 5.x 源码
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!