这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战」
前言
推断构造方法,其实之前我们也经过了:
-
在创建bean的时候,我们不可避免地需要通过构造方法来创建bean实例。
- 在循环依赖、依赖注入中,针对构造方法,我们也有说到对应的相关处理。
这里有一些工作中的小tips:
- 如果在类中声明了多个构造方法并且没有无参的,并且没有用@Autowired标注的构造方法,那么就会报错。
- 如果通过getBean以及@Lazy的方式,或者自己写入BD且指定了构造方法,或者指定AutowireMode=CONSTRUCTOR,也可以绕过这一校验。
这里就看看这里是如何进行推断的,以及具体是如何工作的。
根据Bean的生命周期,我们也容易得知:代码入口在:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//就是这里
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//...
}
方法代码在下面:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//args:getBean时使用的参数
// Make sure bean class is actually resolved at this point.
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());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//与@Bean有关
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
//看上面的注解,也知道这个东西是跟原型bean构造的缓存相关的
boolean resolved = false;
boolean autowireNecessary = false;
//这里的args代表的是希望调用的构造方法的参数,如果是null才会去查看是否有缓存
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
//这里表示的是:是否有构造方法的参数值被缓存,又可能没有经过这里,也有可能解析决定使用的构造方法是无参构造方法
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//有缓存
if (resolved) {
//且有入参值被缓存
if (autowireNecessary) {
//在这里会用缓存来生成【1】
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
//根据上面的逻辑:这里就是来查找构造方法了【3】
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//看这里的方法和【1】是相同的,就代表后面两个参数缺省时会去查找缓存
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);
}