回顾
前面已经看了在加载Bean的时候,如何去解决循环依赖的问题,解决完循环依赖,就到创建Bean的步骤了,而创建bean的步骤是紧紧接着
创建Bean实例
Bean根据范围会分为几种
- 单例
- 原型
- 自定义范围
每种范围都会有自己不同的生命周期
创建单例Bean
源码如下
// Create bean instance.
//判断是不是单例模式
if (mbd.isSingleton()) {
//调用getSingleton方法
sharedInstance = getSingleton(beanName, () -> {
try {
//创建Bean
return createBean(beanName, mbd, args);
}catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
//出现异常就销毁Bean
destroySingleton(beanName);
throw ex;
}
});
//调用getObjectForBeanInstance的将bean转化为对应的JavaBean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
可以看到这里的逻辑只是一个上层调用,主要分为两步
- 创建单例Bean
- 将创建的单例Bean转为Java的Object
getSingleton方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
//断言beanName不能为Null
Assert.notNull(beanName, "Bean name must not be null");
//对singletonObjects容器进行上锁
//这个容器是存储beanName与beanObject的ConcurrentHashMap
synchronized (this.singletonObjects) {
//从容器中根据beanName去获取该beanObject
Object singletonObject = this.singletonObjects.get(beanName);
//如果容器中没有就需要进行创建beanObject
if (singletonObject == null) {
//如果正在销毁单例
if (this.singletonsCurrentlyInDestruction) {
//抛出异常
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
//如果没有进行销毁单例bean
//开启日志追踪
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//创建beanObject的前方法
beforeSingletonCreation(beanName);
//newSingleton标志是否创建成功
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//调用参数传来的ObjectFactory传来的
singletonObject = singletonFactory.getObject();
//将标志位改为true
newSingleton = true;
}
//捕捉异常并进行处理
//而且这里捕捉异常是处理同时创建问题
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
// 如果两个单例Object同时出现,一般来说不会有这个问题,因为synchronic都上锁了
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
//捕捉创建bean的异常
catch (BeanCreationException ex) {
//如果开启了异常记录
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//最终执行创建单例的后方法
afterSingletonCreation(beanName);
}
//如果创建成功
if (newSingleton) {
//进行添加进容器中
addSingleton(beanName, singletonObject);
}
}
//返回singletonObject
return singletonObject;
}
}
可以看到这个方法也是一个比较上层的方法,调用创建Bean的方法,并且对异常做一些捕捉处理
- 对容器进行上锁
- 执行创建Bean的前方法
- 创建Bean,执行传进来的ObjectFactory接口
- 捕捉异常处理
- 执行创建Bean的后方法
- 将创建的singletonObject添加进容器中
- 返回创建好的singletonObject
ObjectFactory
这是一个函数式接口里面只有一个getObject方法
这个函数式接口是在前面传入一个lambda表达式的
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
而且从这里看到一个Lambda表达式的优点,lambda表达式里面的方法可以引用外层的参数,即使不传参进来
可以看到创建Bean和销毁Bean的方法,下面就分析一下这两个方法
createBean
createBean方法由AbstracatAutowireCapableBeanFactory进行实现,从类名大概就可以摸索出这个类去执行一些自动注入的事情
源码如下
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//开启日志
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
//存储前面解析出来的RootBeanDefinition
RootBeanDefinition mbdToUse = mbd;
//下面这步是确保找到一个适合的class来进行反射转换
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
//找到了之后
//新创建RootBeanDefinition
mbdToUse = new RootBeanDefinition(mbd);
//并且装配上适合的beanClass
mbdToUse.setBeanClass(resolvedClass);
}
//准备进行方法重写
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//如果是使用代理的话,那就创建代理对象进行返回,就是AOP
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//如果不是代理的话,调用doCreateBean方法进行创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
//返回创建的beanInstance
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);
}
}
大概总结一下这个方法
- 寻找beanDefinition可以进行转化的class对象,确保可以完成bean转化
- beanDefinition准备方法进行重写
- 创建beanObject
- 先尝试进行创建成代理,而不是目标beanObject
- 如果创建成代理失败,才进行创建目标beanObject
从前面代码看可以知道,调用createBean方法在先经过前处理,下面就先看看前处理是什么操作
createBean的前处理:beforeSingletonCreation
在对存储创建好的beanObject容器上锁后,接下来就是执行前处理了
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
可以看到,前处理仅仅只是做了检查处理
- 判断该beanName是否位于inCreationCheckExclusions容器中,这个容器里面存储的是不需要检查的beanName
- 如果位于inCreationCheckExclusions容器中,代表该beanName不需要进行检查
- 如果不位于里面就代表需要检查,此时再将beanName添加进singletonsCurrentlyInCreatin容器里面,前面已经提到过这个容器是存储正在创建的bean的beanName,也就是创建缓存(检查循环依赖的时候用到过)
- 总的来说这个方法就是加载单例前,先去记录状态的(添加进singletonsCurrentlyInCreation容器中代表正在创建)
createBean的后处理:afterSingletonCreation
源码如下
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
可以看到这端代码其实就是去除单例Bean的状态,因为已经创建好了,就没有必要去保留状态了
- 判断该beanName是否位于inCreationCheckExclusion容器中,这个容器里面存储的是不需要检查的beanName
- 如果位于inCreationCheckExclusion容器中,就代表beanName不需要进行检查
- 如果不位于里面,那么此时就需要将beanName从singletonsCurrentlyInCreation容器中进行移除,也就是去移除加载单例前记录的状态,创建完已经不需要保留状态了
执行ObjectFactory的createBean
进行前处理后,已经可以判断该beanName还没有被创建,下面就可以开始creatBean了,也就是准备去创建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
RootBeanDefinition mbdToUse = mbd;
//下面这步是确保找到一个适合的class来进行反射转换
//其实就是锁定class,根据设置的class属性或者className来进行解析
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
//找到了之后
//新创建RootBeanDefinition
mbdToUse = new RootBeanDefinition(mbd);
//并且装配上适合的beanClass
mbdToUse.setBeanClass(resolvedClass);
}
//准备进行方法重写
// Prepare method overrides.
try {
//验证以及准备覆盖的方法
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//如果是使用代理的话,那就创建代理对象进行返回,就是AOP
//这里其实是尝试给BeanPostProcessors来替代真正的实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//如果不是代理的话,调用doCreateBean方法进行创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
//返回创建的beanInstance
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);
}
}
大概总结一下这个方法
- 寻找beanDefinition可以进行转化的class对象,确保可以完成bean转化,也就是去锁定class,一般是根据据设置的class属性或者根据beanName来进行解析
- beanDefinition准备方法进行重写,在配置文件中没有重写的方法,那这两个容器干嘛的呢?
- 其实前面我们是解析过了bean标签里面的lookup-method以及replace-method,这两个的配置会统一存放在BeanDefinition的methodOverrids属性里,而准备进行重写其实也就是针对这两个属性的!!!
- 而这两个属性其实就是一个拦截器代理的作用,动态地为当前bean生成代理并使用对应的拦截器为bean做增强处理
- 创建beanObject
- 先尝试进行创建成代理beanProcess,而不是目标beanObject
- 如果创建成代理失败,才进行创建目标beanObject
处理override属性
对应的方法为prepareMethodOverrides,注意是RootBeanDefinition进行调用
源码如下,并且该方法位于AbstractBeanDefinition中
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
//判断该beanDefinition有没有overrides属性
//也就是有没有那两个属性
if (hasMethodOverrides()) {
//如果有,获取底层的set集合,即所有的overrids属性,并且每个都去执行prepareMethodOverride方法
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
从底层可以看到,AbstractBeanDefinition使用MethodOverrids对象进行储存这些Overrides属性,并且其底层说白了就是一个Set集合,并且是一个CopyOnWriteArraySet,而且里面存储的元素是MethodOverride,而且其进行判空就是根据底层的set集合是否为空来进行判断的
如果不为空,接下来就要获取这个set集合然后来进行遍历处理了,处理的主要方法为prepareMethodOverride
下面就来看看是如何进行prepare的
源码如下
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
//获取对应类中方法名的个数
//使用class,方法名,通过反射区获取方法名的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
//如果没有找到方法就抛错
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
//如果有一个方法,对bean进行标记,表明没有发送重载
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
// 标记MethodOverrid,但此时暂未进行覆盖,因为这样做可以避免类型检查的开销
mo.setOverloaded(false);
}
}
可以看到,这里准备对方法进行代理重写,其实本质上是判断类里面对应的方法有没有发生重载!!!
因为,对指定方法名进行代理重写,如果发生了重载,就需要对参数类型进行检查,才可以准确定位到具体代理重写哪个方法,但参数类型进行检查是要进行开销的,但如果没有发生方法重载,就不需要进行参数类型检查的,因为就只有一个方法,所以Spring这里将判断方法是否发生重载的放在了这里
说白了,所谓准备方法代理重写,本质上就是判断有没有发生方法重载,如果没有发生方法重载,那么将overLoaded标志位设为false,当真正准备代理重写方法的时候就不需要进行参数类型检查了
而且关键的是,这里不仅仅对方法重载进行了检查,还对方法的存在性进行了检查!!!
实例化的前置处理
实例化的前置处理的作用是:能不能用beanProcessor来代理,而不是直接去创建目标bean,也就是AOP的功能
对应的方法为:resolveBeforeInstantiation
源码如下
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
//使用一个Object对象存储处理结果
Object bean = null;
//判度该RootBeanDefinition是否已经被前置处理过
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// 判度有没有处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//执行前方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//前方法如果返回结果不为空,执行后方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
//修改RootBeanDefinition的前置处理标志位
//如果bean不为空,代表前置处理是成功的
//如果bean为空,代表前置处理是不成功的
mbd.beforeInstantiationResolved = (bean != null);
}
//返回前置处理完后的bean
return bean;
}
可以看到,实例化的前置处理分为了前后处理
- 首先去判断当前RootBeanDefinition是否已经进行过前置处理了
- 没有进行的话就判断是否拥有处理器
- 如果有处理器的话就执行前后处理
- 最后将前置处理的标志位重新设置
- 如果结果不为Null,那就代表前置处理完毕了
- 如果结果为Null,那就代表代表前置处理是失败的
- 没有进行的话就判断是否拥有处理器
前处理
源码如下
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
可以看到,前处理是针对所有的InstantiationAwareBeanPostProcessor进行处理,每个都去执行postProcessBeforeInstantiation方法,经过前处理过后,Bea已经不再是BeanDefinition了,已经转变成一个Object了,也就是经过这个方法后,bean或许已经成为了一个代理Bean了
后处理
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
从代码中,可以看到,后处理是针对所有的BeanPostProcessor进行处理,每个都去执行postProcessAfterInitialzation方法
Spring规定了在初始化Bean后,需要尽可能地将注册的后处理器的postProcessAfterInitialization方法尽可能应用到该bean中
对于前后处理,现在仅仅知道在创建Bean会执行前置处理,前置处理也分为前后处理即可
创建常规bean
经过实例化的前置处理之后,假如没有返回任何结果,那就代表不能去创建一个代理对象,只能去进行常规的实例化bean了
对应的就是createBean里面的doCreateBean方法
源码如下
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
//BeanWrapper是bean的一个压缩对象
BeanWrapper instanceWrapper = null;
//判断是不是单例
if (mbd.isSingleton()) {
//如果是单例的话,先要去清一下缓存
//Spring使用factoryBeanInstanceCache容器来存储一些未完成的工厂Bean
//factoryBeanInstanceCache是一个ConcurrentHashMap
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//如果缓存中不存在
if (instanceWrapper == null) {
//根据指定的bean使用对应的策略创建新的实例
//比如 工厂方法、构造函数自动注入、简单初始化
//生成一个bean的压缩对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//通过压缩对象去获取bean的Object对象
Object bean = instanceWrapper.getWrappedInstance();
//从压缩对象去获取的class
Class<?> beanType = instanceWrapper.getWrappedClass();
//如果beanType不是NullBean类型的class对象
if (beanType != NullBean.class) {
//将RootBeanDefinition的目标class类型进行锁定
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 对RootBeanDefinition的postProcessingLock进行上锁
synchronized (mbd.postProcessingLock) {
//
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 该bean是否需要提前曝光,而且这里的曝光是针对
// 当前创建的RootBeanDefinition是单例、且允许循环依赖,并且该beanName正在创建中
// 也就是说这里进行提前曝光是曝光的是单例Bean,并且开启了循环依赖的
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//进入到这里就代表要对此时创建的单例Bean进行提前曝光了
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//并且这里提前曝光的是,曝光在二级和三级缓存
//避免产生循环依赖问题
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//
Object exposedObject = bean;
try {
// 对bean进行填充
populateBean(beanName, mbd, instanceWrapper);
// 调用bean的init-method方法,也就是开始进行初始化了
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//
if (earlySingletonExposure) {
//检测循环依赖(前面看过的getSingleton方法)
//从一、二、三级缓存中取出该BeanName的单例,
Object earlySingletonReference = getSingleton(beanName, false);
//假如检测到循环依赖,也就是已经被提前曝光过了
//其实这里主要就是检测自己是否已经被曝光了,从之前缓存中取
if (earlySingletonReference != null) {
//再判断暴露的bean是否被增强了
//也就是执行了method-init方法后,是否被代理了
if (exposedObject == bean) {
//如果没被增强,那还是为之前提前曝光的
//通过之前在缓存中曝光的与现在的进行比较
//判断
exposedObject = earlySingletonReference;
}
//如果不等于,那就说明被代理了
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
//再次去检测依赖,这里是去检测依赖的bean是否都已经加载完
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
//遍历所有依赖bean
for (String dependentBean : dependentBeans) {
//
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//判断依赖的bean是否都已经创建完
//如果actualDependentBeans集合不为空,证明依赖的bean都还没有创建完
if (!actualDependentBeans.isEmpty()) {
//抛错
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
//最后根据scope去进行注册bean
//并且看到这个方法名字IfNecessary
//也就是说bean可能会进行注册也可能不注册
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
//返回bean
return exposedObject;
}
常规去创建Bean还挺复杂的
- 先判断是不是单例
- 如果是单例,就需要清空一下正在工厂的缓存,并且工厂将缓存里面的BeanWrapper拿出来
- 如果缓存中没有Wrapper,证明是第一次创建,而且前面没有线程在进行创建,那么就需要去创建BeanWrapper,将BeanDefinition转为BeanWrapper
- 判断BeanWrapper的class对象是否属于BeanNull.class
- 如果不属于就将RootBeanDefinition的targetClass设为BeanWrapper的class
- 锁定RootBeanDefinition的class
- 进行提前曝光bean,这里是在二三级缓存中添加
- 对bean进行填充信息
- bean执行method-init方法,也就是初始化
- 从单例缓存中取出beanName的缓存,使用缓存中的bean与此时的bean进行比较
- 判断此时的bean是否被增强了,也就是有没有method-init方法调用,被AOP代理了
- 如果没被增强,让bean为循环依赖里面的对应bean
- 如果被增强了,遍历所有的依赖bean,如果有依赖bean还没有创建完,抛错
- 判断此时的bean是否被增强了,也就是有没有method-init方法调用,被AOP代理了
- 如果没有出现循环依赖,什么都不做
- 根据scope去注册bean
- 返回bean
大概理解了整个创建常规Bean的过程之后,下面就看下每一个步骤了
createBeanInstance
从代码上可以知道,这个方法就是当工厂缓存中没有对应的beanWrapper时,将BeanDefinition转为BeanWrapper的
源码如下
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//解析BeanDefinition的class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//
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());
}
//消费型接口
//如果RootBeanDefinition有提供消费型获取Bean的方式
//使用RootBeanDefinition提供的获取Bean的方式
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果RootBeanDefinition的工厂方法不为空则使用工厂方法进行初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
//如果RootBeanDefinition既没有自己的获取Bean方式,也没有工厂方法
//大多数是这种情况
//resolver判断是否锁定了构造方法
boolean resolved = false;
//autowireNecessary判断是不是自动装配
//其实这个变量是用来判断该RootBeanDefinition是否已经解析过了
boolean autowireNecessary = false;
//下面就开始常规创建Bean
//判断传来的构建参数是否为空,即没有指定的构建参数
if (args == null) {
//如果没有构造参数
//代表肯定是使用无参构造方法来进行创建的
//对RootBeanDefinition的constructorArgumentLock进行上锁
//这里其实相当于在对缓存上锁
synchronized (mbd.constructorArgumentLock) {
//对于RootBeanDefinition可能会拥有多个构造方法
//所以这里需要对使用的构造方法进行锁定
//如果RootBeanDefinition的构造方法和工厂方法不为空
//RootBeanDefiniton的resolverConstructorOrFactoryMethod其实是一个缓存
//如果从缓存中存在解析结果,那就会尝试从缓存中取
if (mbd.resolvedConstructorOrFactoryMethod != null) {
//锁定了构造方法
resolved = true;
//自动注入由RootBeanDefinition来决定
//constructorArgumentsResolved代表该RootBeanDefinitiony是否被解析过了
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果锁定了构造方法
if (resolved) {
//如果已经解析过
if (autowireNecessary) {
//构造函数进行自动注入
return autowireConstructor(beanName, mbd, null, null);
}
//如果没有解析过
else {
//使用默认的构造函数构造,也就是无参构造
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
//如果构造参数不为空,那么代表需要判断使用哪种构造方法了
//获取beanName对应的beanClass的所有构造器
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//如果构造器不为空
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//自动注入创建Bean
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
//采用默认构造函数创建,也就是无参方法!!!
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
从这里可以看到,其实创建常规BeanWrapper分为两种
- 自动注入
- 无参方法构造
整个过程大致如下
- 如果RootBeanDefinition中存在factoryMethodName属性,既在配置文件上添加了factory-method方法,那么Spring就会尝试使用instantiateUsingFactoryMethod方法进行创建Bean,根据RootBeanDefinition中的配置生成Bean的实例
- 根据有无构造参数来选定创建bean的方法,也就是选用什么构造函数
- 如果没有构造参数,那就不需要对构造函数进行解析了,不过需要去看缓存里面有没有,先判断resolvedConstructorOrFactoryMethod缓存是否为空,在RootBeanDefinition里面有一个标志位constructorArgumentsResolved,该标志位可以判断这个RootBeanDefinition是否已经解析过(注意只是解析),如果解析过,优先使用autowireConstructor方法进行创建 ,如果缓存中没有就使用**instantiateBean(beanName, mbd);**方法进行创建,该方法调用的是无参构造方法
- 如果拥有构造参数,那就需要对构造函数进行解析了,不过同样也要去缓存里面看是否已经解析过
- 首先获取所有的构造器
- 将所有的构造器传入autowireConstructor方法里面进行解析,选择使用哪个构造器来创建Bean
从这里可以看到,Spring对于BeanWapper的创建还利用了缓存技术,通过RootBeanDefinition的resolvedConstructorOrFactoryMethod来进行缓存解析过的方法,也可以判断出,在两种创建Bean方法之后,应该会添加进缓存里面
autowireConstructor
从上面代码可以看到,当该Bean已经被解析过,并且缓存存在的话,会使用autowireConstrutor,并且当携带构造参数来进行创建Bean的话,也会使用autowireConstructor方法进行创建Bean
源码如下
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
可以看到,其是交由ConstructorResolver去负责执行的
具体的细节如下
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
//判断传进来的构造参数是否为空
if (explicitArgs != null) {
//如果传进来的构造参数不为空,直接使用传进来的参数
argsToUse = explicitArgs;
}
else {
//如果参数为空
//就会尝试去配置文件上去获取
Object[] argsToResolve = null;
//对缓存进行上锁,因为要利用到缓存,所以这里不允许其他线程对该RootBeanDefinition的缓存修改
synchronized (mbd.constructorArgumentLock) {
//调用RootBeanDefinition的resolvedConstructorOrFactoryMethod缓存中取构造器
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
//如果缓存中有,且RootBeanDefinition已经被解析过(通过标志位判断)
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
//取出缓存的之前解析使用的构造参数
argsToUse = mbd.resolvedConstructorArguments;
//如果之前解析使用的构造参数为空
if (argsToUse == null) {
//取出配置文件上的构造参数
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
//释放缓存锁了,因为已经对缓存操作完了
//如果配置文件上的构造参数不为空,则需要使用到配置文件上的构造参数
if (argsToResolve != null) {
//对构造参数进行解析
//其实这里解析的是构造参数的类型,因为配置上面全部为字符串
//所以需要根据构造函数的参数类型对其进行转化
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
//此时已经解决了构造参数的问题了
//下面是选择构造器的问题
//从这个if开始直到差不多最下面,都是解决构造器问题
//前面已经尝试过从缓存中取构造器了,并且已经解决了构造参数的问题
//但如果缓存中没有构造器,或者构造参数仍然为空(配置文件上都没有构造参数)
//就需要进行处理
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
//chosenCtors是传进来的所有构造器
Constructor<?>[] candidates = chosenCtors;
//判断有没有构造器
if (candidates == null) {
//如果没有构造器
//取出RootBeanDefinition的class对象
Class<?> beanClass = mbd.getBeanClass();
try {
//RootBeanDefinition里面有个反射是否可以获取私有属性或方法的标志位(默认为True)
//通过这个标志位去获取构造器
//如果允许获取私有的,就获取包括私有的所有构造方法
//如果不允许获取私有的,只获取声明的构造方法
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);
}
}
//如果通过反射找到了构造器,有且仅有一个构造器
//并且传进来的构造参数为空,并且RootBeanDefinition从配置文件上没有构造参数
//那么这里就会猜测是不是无参构造
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
//获取里面唯一的构造器
Constructor<?> uniqueCandidate = candidates[0];
//如果构造器里面需要方的参数数量为0,那么久代表是一个无参构造器
if (uniqueCandidate.getParameterCount() == 0) {
//对RootBeanDefinition的constructorArgumentLock进行上锁
synchronized (mbd.constructorArgumentLock) {
//将构造器添加进缓存(这里的缓存只有一个)
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
//将解析的标志位设置为true,代表该RootBeanDefinition已经被解析过了
mbd.constructorArgumentsResolved = true;
//同理将构造参数添加进缓存中,并且为EMPTY_ARGS
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
//对缓存操作完了就释放锁
//下面就是开始利用无参构造实例化Bean
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
//如果参数数量不为0,代表不是无参构造,不做仍和处理
}
//如果不是无参构造,就还需要下一步处理
// Need to resolve the constructor.
//此时是既没有被缓存,而且还不是无参构造(之前代码是没有先判断无参构造的)
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
//声明ConstructorArgumentValues来存储构造参数
ConstructorArgumentValues resolvedValues = null;
//minNrOfArgs用于表示构造参数个数
int minNrOfArgs;
if (explicitArgs != null) {
//如果有传来构造参数,以传来的构造参数为主
//参数的数量就为传进来构造参数的数量
minNrOfArgs = explicitArgs.length;
}
else {
//取出RootBeanDefinition存储的配置文件的构造参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
//创建ConstructorArgumentValues,用于存储构造参数
//注意:只要当传来的构造参数为空时,才创建ConstructArgumentValues
resolvedValues = new ConstructorArgumentValues();
//对所有的构造参数进行解析,并且返回解析出来的构造参数个数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//对构造器进行排序,具体规则如下
//public构造函数优先参数数量降序、非Public构造函数参数数量降序
//即参数数量越少,优先级越高
AutowireUtils.sortConstructors(candidates);
//这个minTypeDiffWeight是用来记录构造器的参数类型与构造参数类型的不同的数量的
int minTypeDiffWeight = Integer.MAX_VALUE;
//这个ambiguousConstructors是用来记录差异一样的构造器(比之前遇到的构造器更不相似就会淘汰)
Set<Constructor<?>> ambiguousConstructors = null;
Deque<UnsatisfiedDependencyException> causes = null;
//对所有构造器进行遍历
//此时Candidates已经根据参数数量来排序了
for (Constructor<?> candidate : candidates) {
//构造器需要的参数个数
int parameterCount = candidate.getParameterCount();
//这里最重要的判断是,如果前面解析的构造参数的个数大于构造器需要的参数个数
//就代表找不到了,因为后面的参数个数会更多
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果参数个数少了,Continue下一轮循环
if (parameterCount < minNrOfArgs) {
continue;
}
//来到这步就代表着
//参数个数是符合要求的
//声明ArgumentsHolder来存储参数
ArgumentsHolder argsHolder;
//获取参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
//下面就是要开始匹配参数的class类型
//当传来的构造参数为Null时,这里才不等于Null
//因为上面的判断就是当传来的构造参数为Null时,才会去创建ConstructArgumentValue
if (resolvedValues != null) {
try {
//获取参数的名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
//如果参数的名称为空
if (paramNames == null) {
//获取参数名称搜索器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//使用参数名称搜索器去获取构造器的参数名称
paramNames = pnd.getParameterNames(candidate);
}
}
//根据参数名称和数据类型去创建ArgumentsHolder
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
//如果传了构造参数进来
//那就需要以传进来的构造参数为主
else {
// Explicit arguments given -> arguments length must match exactly.
//再次检查数量
if (parameterCount != explicitArgs.length) {
continue;
}
//如果数量正确,ArgumentsHolder以传进来的参数来创建
argsHolder = new ArgumentsHolder(explicitArgs);
}
//探测是否有不确定性的构造函数存在
//比如不同构造函数的参数为父子关系
//返回的是参数类型不同的个数
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 判断当前构造方法的差异是不是小于minTypeDiffWeigh
//minTypeDiffWeigh记录前面构造方法的最小差异
if (typeDiffWeight < minTypeDiffWeight) {
//如果小于,更新constructotToUser为当前的构造方法
constructorToUse = candidate;
//更新构造参数的承载
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
//更新最小的差异
minTypeDiffWeight = typeDiffWeight;
//将前面的那些构造方法记录清空
ambiguousConstructors = null;
}
//如果出现等于的情况
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
//记录进ambiguousConstructors里面
//相当于记录了差异一样的构造器
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//如果最后都没有找到构造器
if (constructorToUse == null) {
//抛出异常
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//如果找到了构造器,但后续出现差异类似的构造器
//即ambiguousConstructors集合不为空
//那就无法做出选择
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
//抛错处理
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//最后就是将解析的构造函数添加进缓存中
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
//再次判断构造参数是否为空
Assert.state(argsToUse != null, "Unresolved constructor arguments");
//进行创建Bean
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
这个代码逻辑真的长。。。
总结一下,这个方法主要做了两件事情
- 对参数进行处理
- 对构造器进行处理
只有先确定了参数才可以确定构造器,大概步骤如下
- 确定构造函数的参数
- 根据传进来的explicitArgs,如果不为空,就使用这个
- 如果为空,先尝试从缓存中获取
- 缓存中没有,就从配置文件上获取
- 构造函数的确定
- 遍历所有的构造器,锁定参数个数与前面确定参数个数一样的构造器
- 因为此时构造器已经进行排序了,主要是按照参数个数进行降序排,所以,个数只要大于就直接break,个数小于就continue,只对个数一样的进行处理
- 处理操作如下
- 获取参数的所有名称,这是因为constructor-arg标签是支持指定参数名称进行设定参数值的情况
- 根据确定的构造函数转换对应的参数类型
- 根据前面确认的参数class类型来获取构造函数的差异,因为可能存在class不对应,或者不同构造器的参数存在父子关系
- 选取最小差异的构造器,后续如果出现更小差异的就进行替换,出现相同差异的存放在Set集合里面(具体来说是一个LinkedHashSet)
- 如果后面出现了多个最小差异的,抛错处理
- 最后就是根据选定的构造器与选定的构造参数进行创建Bean