你知道Spring怎么肯定实例化对象的构造器吗?

你的赞是我最大的动力,期待与你共同进步web

1.开篇

  上一篇文章学习了在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

2 你真的知道Spring如何选择构造器吗?

  文章开始以前,仍是要从使用场景入手,而后在经过源码来分析,毕竟源码是不会骗人的。。。编辑器

2.1情形一
@Service
public class DemoServiceOne {  } 复制代码
2.2情形二
@Service
public class DemoServiceOne {  @Autowired  DemoServiceTwo demoServiceTwo;   public DemoServiceOne(){}   public DemoServiceOne(DemoServiceTwo demoServiceTwo){  this.demoServiceTwo = demoServiceTwo;  } } 复制代码
2.3情形三
@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;  } } 复制代码
2.4情形四
@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;  } } 复制代码

3 AutowiredAnnotationBeanPostProcessor 类中的方法

  从代码的实现能够看出,对于一个放在注册到容器中的 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<?>[] rawCandidatespost

rawCandidates = beanClass.getDeclaredConstructors();无参构造器也会被拿到。下图中,以类中没有构造器的情形举例学习

获取类的构造器 ②: for 循环 rawCandidates 对其中的每个构造器进行判断flex

③:判断构造器上是否加了注解ui

  • 3.1 有加注解

    先判断requiredConstructor集合是否为空, 若不为空则表明以前已经有一个required=true的构造器了,两个true将抛出异常. 再判断candidates 集合是否为空,若不为空则表示以前已经有一个打了注解的构造器,如有required又是true,抛出异常. 若上述判断都经过了,将当前构造器赋值给 requiredConstructor集合中,再放入candidates集合中。

  • 3.2 没有加注解

    若是是无惨构造器则赋值给 defaultConstructor,其余的构造器不作处理,在会后返回的时候返回null

④:没有加注解且参数的个数为 0。将当前 for 循环的构造方法赋值给 defaultConstructor

defaultConstructor = candidate;
复制代码

⑤:肯定构造器 肯定构造器   这里肯定构造器仍是要结合前面的代码去看。

4 情形分析

  • 构造器上没有注解的状况:

    • 无参构造器将直接加入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 则正常经过,后面的方法会肯定使用哪个

5 总结

    1. 对象中存在多个未被注解的构造器 determineCandidateConstructors()方法都会返回 null这里有彩蛋,后面文章会提到
    1. 对象中有且仅有一个未被注入的构造器

      • 若该构造器为无参的,那么 determineCandidateConstructors()返回 null
      • 若该构造构器为有参的,那么 determineCandidateConstructors()返回 该构造器
    1. 仅有一个注入的构造器,则使用该构造器
    1. 有两个注入的构造器
      • required 都为 true 抛出异常
      • required 一个为 true 另外一个为 false 抛出异常
      • required 都为 false 正常经过

  这篇文章中对Spring中经过使用 BeanPostProcessor 的实现类来完成构造器的确认进行了分析。当咱们实例化一个对象的时候,构造方法肯定了, 那么就能够经过使用构造方法来实例化了。可是,经过上面的分析发现,可能会有多个构造方法存在的状况,那么在这种状况下,Spring是如何肯定使用哪一个构造方法的, 也就是大名鼎鼎的推断构造器,下一篇文章中,将进行分析。

本文使用 mdnice 排版

相关文章
相关标签/搜索