❝你的赞是我最大的动力,期待与你共同进步web
❞
上一篇文章学习了在Spring中如何经过工厂方法来实例化对象的,详细分析了createBeanInstance()
方法中调用的instantiateUsingFactoryMethod()
方法,今天这个片文章,未来分析另外一个被调用的方法 determineConstructorsFromBeanPostProcessors()
。方法入口以下: 在这个的实现中,咱们又看到了很是熟悉的
BeanPostProcessors
的处理,代码以下:缓存
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException { if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null) { return ctors; } } } } return null; } 复制代码
从上述代码中,能够看到 Spring 中的处理方式就是先获取到全部的 BeanPostProcessors
的子类实现,而后循环判断,若是有符合条件的, 那么就调用该类的 determineCandidateConstructors()
方法,完成相应的处理。 在文章正式开始以前,又到了问问题的时候了,
ibp.determineCandidateConstructors()
在执行 determineCandidateConstructors()
方法的 BeanPostProcessor
的实现类中,有一个 AutowiredAnnotationBeanPostProcessor
, 我这里有一个问题,就是这个类是在何时放到 BeanDefinitionMap
中的呢?「请查看Spring容器初始化之先发五虎」。app
文章开始以前,仍是要从使用场景入手,而后在经过源码来分析,毕竟源码是不会骗人的。。。编辑器
@Service
public class DemoServiceOne { } 复制代码
@Service
public class DemoServiceOne { @Autowired DemoServiceTwo demoServiceTwo; public DemoServiceOne(){} public DemoServiceOne(DemoServiceTwo demoServiceTwo){ this.demoServiceTwo = demoServiceTwo; } } 复制代码
@Service
public class DemoServiceOne { @Autowired DemoServiceTwo demoServiceTwo; @Autowired DemoServiceThree demoServiceThree; public DemoServiceOne(DemoServiceTwo demoServiceTwo){ this.demoServiceTwo = demoServiceTwo; } public DemoServiceOne(DemoServiceThree demoServiceThree, DemoServiceTwo demoServiceTwo){ this.demoServiceTwo = demoServiceTwo; this.demoServiceThree = demoServiceThree; } } 复制代码
@Service
public class DemoServiceOne { @Autowired DemoServiceTwo demoServiceTwo; @Autowired DemoServiceThree demoServiceThree; public DemoServiceOne(DemoServiceTwo demoServiceTwo){ this.demoServiceTwo = demoServiceTwo; } @Autowired public DemoServiceOne(DemoServiceThree demoServiceThree, DemoServiceTwo demoServiceTwo){ this.demoServiceTwo = demoServiceTwo; this.demoServiceThree = demoServiceThree; } } 复制代码
从代码的实现能够看出,对于一个放在注册到容器中的 BeanName
,都会作一次这个判断。至于没有交给Spring的类,这里固然是不会作处理了。ide
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException { // Let's check for lookup methods here... // 首先检查 lookup 方法 if (!this.lookupMethodsChecked.contains(beanName)) { try { ReflectionUtils.doWithMethods(beanClass, method -> { Lookup lookup = method.getAnnotation(Lookup.class); if (lookup != null) { Assert.state(this.beanFactory != null, "No BeanFactory available"); LookupOverride override = new LookupOverride(method, lookup.value()); try { RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName); mbd.getMethodOverrides().addOverride(override); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(beanName, "Cannot apply @Lookup to beans without corresponding bean definition"); } } }); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Lookup method resolution failed", ex); } this.lookupMethodsChecked.add(beanName); } // Quick check on the concurrent map first, with minimal locking. // 从缓存中查找 Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass); // 缓存中没有 if (candidateConstructors == null) { // 同步代码块 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 大小为 前面获取到的类的构造参数个数 List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length); //存放依赖注入的required=true的构造器 Constructor<?> requiredConstructor = null; //存放默认构造器 Constructor<?> defaultConstructor = null; //获取主要的构造器,大多数的状况下为 null Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass); int nonSyntheticConstructors = 0; for (Constructor<?> candidate : rawCandidates) { // 判断构造器是否为合成构造器,只要是咱们本身申明的都不是合成构造器 if (!candidate.isSynthetic()) { // 不是合成构造器,标记非合成构造器的数字 加一 nonSyntheticConstructors++; } else if (primaryConstructor != null) { continue; } //查找当前构造器上的注解,有些构造器上面可能有注解,有些没有。这里要作区分 AnnotationAttributes ann = findAutowiredAnnotation(candidate); if (ann == null) { // 没有注解 // 获取建立 Bean使用的 class Class<?> userClass = ClassUtils.getUserClass(beanClass); if (userClass != beanClass) { try { Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes()); ann = findAutowiredAnnotation(superCtor); } catch (NoSuchMethodException ex) { // Simply proceed, no equivalent superclass constructor found... } } } if (ann != null) { // 有注解 if (requiredConstructor != null) { //已经存在一个required=true的构造器了,抛出异常 throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate + ". Found constructor with 'required' Autowired annotation already: " + requiredConstructor); } //判断此注解上的required属性 默认为 true 可设置为 false // 这里是用来处理两个注解一个 required 为 true,一个 为false的状况 boolean required = determineRequiredStatus(ann); if (required) { if (!candidates.isEmpty()) { throw new BeanCreationException(beanName, "Invalid autowire-marked constructors: " + candidates + ". Found constructor with 'required' Autowired annotation: " + candidate); } //若为true //将当前构造器赋值给 requiredConstructor requiredConstructor = candidate; } // 当前的构造器添加到候选的构造器集合中 candidates.add(candidate); } //若是该构造函数上没有注解,再判断构造函数上的参数个数是否为0 else if (candidate.getParameterCount() == 0) { //若是没有参数,加入defaultConstructor集合,这里能够看出没有构造器的状况下,将无参构造器赋值给默认的构造器 defaultConstructor = candidate; } } //适用的构造器集合若不为空 if (!candidates.isEmpty()) { // Add default constructor to list of optional constructors, as fallback. //若没有required=true的构造器 if (requiredConstructor == null) { if (defaultConstructor != null) { //将defaultConstructor集合的构造器加入适用构造器集合 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]); } //若是适用的构造器集合为空,且Bean只有一个构造器而且此构造器参数数量大于0 else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { //就使用此构造器来初始化 candidateConstructors = new Constructor<?>[] {rawCandidates[0]}; } //若是构造器有两个,且默认构造器不为空 else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { //使用默认构造器返回 candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; } else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { candidateConstructors = new Constructor<?>[] {primaryConstructor}; } else { // 都不符合 初始化 candidateConstructors 若不初始化 后面的判断会有问题 candidateConstructors = new Constructor<?>[0]; } //放入缓存,方便下一次调用,不须要上述的解析过程了,直接在缓存中获取 this.candidateConstructorsCache.put(beanClass, candidateConstructors); } } } // 这里能够看到对 candidateConstructors 的初始化是有意义的 return (candidateConstructors.length > 0 ? candidateConstructors : null); } 复制代码
首先来分析一下上述代码主要住了什么事,选取主要的步骤进行说明:函数
①:首先获取类的构造方法,记录在 Constructor<?>[] rawCandidates
中post
❝rawCandidates = beanClass.getDeclaredConstructors();无参构造器也会被拿到。下图中,以类中没有构造器的情形举例学习
❞
②:
for
循环 rawCandidates
对其中的每个构造器进行判断flex
③:判断构造器上是否加了注解ui
❝先判断requiredConstructor集合是否为空, 若不为空则表明以前已经有一个required=true的构造器了,两个true将抛出异常. 再判断candidates 集合是否为空,若不为空则表示以前已经有一个打了注解的构造器,如有required又是true,抛出异常. 若上述判断都经过了,将当前构造器赋值给 requiredConstructor集合中,再放入candidates集合中。
❞
❝若是是无惨构造器则赋值给 defaultConstructor,其余的构造器不作处理,在会后返回的时候返回null
❞
④:没有加注解且参数的个数为 0。将当前 for
循环的构造方法赋值给 defaultConstructor
defaultConstructor = candidate;
复制代码
⑤:肯定构造器 这里肯定构造器仍是要结合前面的代码去看。
构造器上没有注解的状况:
无参构造器将直接加入defaultConstructor集合中,不管是否申明。可是本方法最后返回的是 null
。最终的实例化是经过默认的构造函数来完成的 instantiateBean(beanName, mbd)
。
在构造器数量只有一个且有参数时,此惟一有参构造器将加入candidateConstructors集合中。最后返回。
在构造器数量大于1个,不管是否申明无参构造器的状况下,将返回一个空的candidateConstructors集合,也就是没有找到构造器。
❝不过这里须要区分一下是否声明无惨构造器: 若是未声明 defaultConstructor 为null 若是声明了 defaultConstructor 不为null
❞
综上所述,在构造器没有注解的状况下,若是有且仅有一个非无惨的构造器,那么本方法返回的就是这个构造器。若是大于一个或则只有一个 无参构造器,那么该方法返回的都是 null
。
构造器上有注解的状况须要判断required属性:
两个构造器上都有 @Autowired
且 required属性都为true 抛出异常
❝throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate + ". Found constructor with 'required' Autowired annotation already: " + requiredConstructor);
❞
两个构造器上都有 @Autowired
一个 required属性都为true 另外一个 required属性都为false 抛出异常
❝throw new BeanCreationException(beanName, "Invalid autowire-marked constructors: " + candidates + ". Found constructor with 'required' Autowired annotation: " + candidate);
❞
两个构造器上都有 @Autowired
且 required属性都为false 则正常经过,后面的方法会肯定使用哪个
determineCandidateConstructors()
方法都会返回
null
。
「这里有彩蛋,后面文章会提到」
对象中有且仅有一个未被注入的构造器
determineCandidateConstructors()
返回
null
determineCandidateConstructors()
返回 该构造器
true
抛出异常
true
另外一个为
false
抛出异常
false
正常经过
这篇文章中对Spring中经过使用 BeanPostProcessor
的实现类来完成构造器的确认进行了分析。当咱们实例化一个对象的时候,构造方法肯定了, 那么就能够经过使用构造方法来实例化了。可是,经过上面的分析发现,可能会有多个构造方法存在的状况,那么在这种状况下,Spring是如何肯定使用哪一个构造方法的, 也就是大名鼎鼎的推断构造器,下一篇文章中,将进行分析。
本文使用 mdnice 排版