文章目录
- 前言
- 一、createBeanInstance
- 1.1、determineConstructorsFromBeanPostProcessors
- 1.2、instantiateBean
- 1.3、autowireConstructor
前言
在Spring中,如果某个bean只有一个无参的构造方法,那么就会根据该构造方法进行实例化:
但是如果存在多个呢?
以及手动使用
@AutoWired
注解,乃至更复杂的情况?
这里就涉及到Spring对于构造方法的推断。构造方法的推断,是属于bean生命周期中的
实例化阶段
:
一、createBeanInstance
createBeanInstance
是对于bean进行实例化
的方法:
- 参数一:将要实例化的bean的名称。
- 参数二:将要实例化的bean的定义。
- 参数三:getBean方法传入的参数。
其中args
参数,可以理解为指定Spring使用何种构造方法:
这样写默认使用的会是无参构造,为什么等会会说明
而在getBean
方法中指定了这个参数,Spring会按照指定的参数去选择构造方法。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 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();//可以在bean定义中指定需要创建哪一个bean//例: beanDefinition.setInstanceSupplier(()->new OrderService());//创建出的就是OrderService的实例if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}//如果bean定义中包含工厂方法名称,则通过工厂方法来实例化beanif (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}//-----------------和构造方法有关的逻辑--------------------//resolved用于标记构造函数是否已解析//autowireNecessary标记是否需要自动装配构造函数。boolean resolved = false;boolean autowireNecessary = false;// // 如果args为null,则检查构造函数是否已经解析并缓存if (args == null) {synchronized (mbd.constructorArgumentLock) {//这个属性保存了bean定义中解析出来的构造函数或工厂方法。//如果这个属性不为null,说明bean的构造函数(或者工厂方法)已经被解析并准备好。if (mbd.resolvedConstructorOrFactoryMethod != null) {//标记resolved为true,表示构造函数已经解析resolved = true;//确定是否需要自动装配。autowireNecessary = mbd.constructorArgumentsResolved;}}}//如果构造函数已解析,则根据是否需要自动装配来决定创建bean的方式。if (resolved) {//如果需要自动装配if (autowireNecessary) {//1.3、autowireConstructor 进行构造函数自动装配return autowireConstructor(beanName, mbd, null, null);}else {//1.2、instantiateBean 直接使用已解析的构造函数实例化bean。return instantiateBean(beanName, mbd);}}//1.1、determineConstructorsFromBeanPostProcessors 构造方法的推论Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);//推断出的构造不为空 或者 bean定义设置成了允许Spring去自己推断构造 或者 bean定义中有构造参数或传入了构造参数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);}//如果没有任何候选构造函数或首选构造函数,则使用默认的无参构造函数实例化bean。return instantiateBean(beanName, mbd);
}
在上面这段代码中,首先会去检查缓存,resolved
表示构造函数是否已解析,而autowireNecessary
表示是否需要自动装配构造函数。那么什么情况下autowireNecessary
会被设置成true?
@Component
public class MyBean {private final OtherBean otherBean;@Autowiredpublic MyBean(OtherBean otherBean) {this.otherBean = otherBean;}
}
mbd.resolvedConstructorOrFactoryMethod != null
表示的是重复创建同一个bean
的情况,Spring可以重用已解析的构造函数,避免每次都解析构造函数。
1.1、determineConstructorsFromBeanPostProcessors
determineConstructorsFromBeanPostProcessors
用于构造方法的推论。能走到该方法,说明:
- 构造函数之前没有被解析,也就是该bean第一次被创建。
- 和传入的
args
无关,无论是否传递该参数,只要条件1满足,都会进行推断。
AbstractAutoProxyCreator是一个空实现,真正的实现是AutoWired…
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)throws BeanCreationException {// 1. 检查是否存在查找方法(@Lookup注解的方法),如果是第一次检查该bean的查找方法,则处理查找方法。if (!this.lookupMethodsChecked.contains(beanName)) {// 如果beanClass是一个候选类if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {try {// 从当前beanClass开始遍历所有继承的类Class<?> targetClass = beanClass;do {// 遍历当前类的所有方法ReflectionUtils.doWithLocalMethods(targetClass, method -> {// 如果方法上有@Lookup注解Lookup lookup = method.getAnnotation(Lookup.class);if (lookup != null) {Assert.state(this.beanFactory != null, "No BeanFactory available");// 创建一个LookupOverride对象,用于后续处理LookupOverride override = new LookupOverride(method, lookup.value());try {// 获取bean的定义RootBeanDefinition mbd = (RootBeanDefinition)this.beanFactory.getMergedBeanDefinition(beanName);// 添加Override到bean的methodOverrides中mbd.getMethodOverrides().addOverride(override);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(beanName,"Cannot apply @Lookup to beans without corresponding bean definition");}}});// 向上遍历父类targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);}}// 将该bean名称标记为已检查过this.lookupMethodsChecked.add(beanName);}// 2. 尝试从缓存中获取该beanClass的构造函数Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {// 3. 如果缓存中没有,进入同步代码块解析构造函数synchronized (this.candidateConstructorsCache) {candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {Constructor<?>[] rawCandidates;try {// 获取bean类的所有构造函数(包括有参和无参的)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);}// 存储候选构造函数List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);// 存储需要的构造函数Constructor<?> requiredConstructor = null;// 存储默认构造函数Constructor<?> defaultConstructor = null;//和Kotlin有关,可以忽略Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);int nonSyntheticConstructors = 0;// 遍历所有的构造函数for (Constructor<?> candidate : rawCandidates) {if (!candidate.isSynthetic()) {//一般情况下的构造函数,nonSyntheticConstructors计数+1nonSyntheticConstructors++; }else if (primaryConstructor != null) {continue; //和Kotlin有关,可以忽略}// 查找构造函数上是否存在@Autowired注解MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);// 如果在当前类找不到,继续查找父类构造函数if (ann == null) {Class<?> userClass = ClassUtils.getUserClass(beanClass);if (userClass != beanClass) {try {// 如果类继承自其他类,查找父类中是否有匹配的构造函数Constructor<?> superCtor =userClass.getDeclaredConstructor(candidate.getParameterTypes());ann = findAutowiredAnnotation(superCtor);}// 如果父类没有对应的构造函数,继续向下执行catch (NoSuchMethodException ex) {}}}//如果构造函数上存在@Autowired注解if (ann != null) {// 如果已找到required标记的构造函数,则抛出异常if (requiredConstructor != null) {//因为一个bean只能有一个required构造函数throw new BeanCreationException(beanName,"Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " +requiredConstructor);}// 判断@Autowired是否标记为requiredboolean required = determineRequiredStatus(ann);if (required) {if (!candidates.isEmpty()) { // 如果已经有候选构造函数// 抛出异常,因为一个bean不能同时有多个required构造函数throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " +candidate);}// 设置为需要的构造函数requiredConstructor = candidate;}// 将构造函数加入候选列表candidates.add(candidate);}else if (candidate.getParameterCount() == 0) {// 如果是无参构造函数,记录为defaultConstructordefaultConstructor = candidate;}}// 如果找到autowire标记的构造函数,处理requiredConstructorif (!candidates.isEmpty()) {// 如果没有找到required为ture构造函数if (requiredConstructor == null) {// 如果有默认构造函数if (defaultConstructor != null) {//将默认构造设置为候选构造函数candidates.add(defaultConstructor);}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));}}candidateConstructors = candidates.toArray(new Constructor<?>[0]);}// 如果只找到一个带参数的构造函数else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {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};}// 如果没有候选构造函数else {candidateConstructors = new Constructor<?>[0];}// 将解析结果缓存起来this.candidateConstructorsCache.put(beanClass, candidateConstructors);}}}// 返回找到的候选构造函数,如果没有找到,则返回null 走默认无参构造的逻辑return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
这一块的逻辑非常复杂,这里仅仅用两种常见的情况进行说明:
一个默认的无参构造,一个有参构造
首先得到OrderService
的所有构造方法:
遍历所有的构造方法:
找注入点,现在
OrderService
上没有任何加了@AutoWired
的构造方法。
Class<?> userClass = ClassUtils.getUserClass(beanClass);
的逻辑:
如果当前bean是被cglib代理过的,就去父类中找。
下一个if也不满足,因为当前构造方法上没有
@AutoWired
第一个遍历到的是无参构造方法,参数的个数为0,所以被标记为默认的构造:
第二个遍历到的是有参构造方法,流程和第一个类似,在执行完这个循环后,
defaultConstructor
被设置成了无参构造,而nonSyntheticConstructors
集合的个数为2:
下面的条件都不满足,会进入最后的else:
最终返回null,返回null代表什么,会在instantiateBean里说明:
再简单地看下加上了@AutoWired
的情况:
第一次循环的是无参构造
,最终会加入defaultConstructor
第二次循环的是带有
@AutoWired
注解的有参构造,找到了注入点:
@AutoWired
注解的required参数默认为true,这里进行了判断,如果有多个加上了@AutoWired
注解,并且没有显式指定required属性,或者required都为true的情况下,会报错。
然后将当前的构造方法设置成需要的构造方法:
在放入缓存后,返回的不是null,而是加上了
@AutoWired
注解的构造:
设置了多个
@AutoWired
注解的构造,会出现异常
简单地小结一下
determineConstructorsFromBeanPostProcessors
方法:如果当前没有加
@AutoWired
注解:
- 多个有参构造,并且有一个无参构造,返回null
- 有多个有参构造,没有默认的无参构造,报错
- 只有一个无参构造,返回null
- 只有一个有参构造,返回该有参构造
如果当前加
@AutoWired
注解:
- 有多个require为true的,报错
- 只有一个require为true的,返回该构造
- 没有require为true的,返回所有构造,包括无参
1.2、instantiateBean
instantiateBean
的底层最终是采用默认的无参构造去创建对象:
1.3、autowireConstructor
autowireConstructor
是处理determineConstructorsFromBeanPostProcessors
方法的返回不为null的逻辑,包括当前没有加@AutoWired
注解,只有一个有参构造的情况,以及如果当前加@AutoWired
注解,只有一个require为true的、没有require为true的情况。
- 参数一:当前bean的名称。
- 参数二:当前bean的定义。
- 参数三:推断出的构造方法。
- 参数四:显式的构造函数参数。
这段代码最复杂的地方在于歧义处理,即:如果存在构造函数的类型匹配度相同的多个候选项,则会处理歧义情况,有机会单独开一篇说明。