Spring源码系列之推断构造方法

本篇博客讲一讲spring是怎么样推断构造方法的?什么意思呢,就是说一个类如果有多个构造方法,spring是怎样推断出来究竟该使用哪个构造方法进行bean的实例化呢?

看下面的例子,先给出以下几个类

@Component
public class OrderService {
}
@Component
public class Student {
}
***我们在注入模型是0的情况下讨论。***
先来一个开胃菜
示例一
@Component
public class UserService {
  public UserService(){
   System.out.println("无参构造方法!!");
  }
  public UserService(Student student){
      System.out.println("一个构造参数");
  }
  public UserService(Student student,OrderService orderService){
      System.out.println("两个构造参数");
  }

}
示例2
//此时会用哪个构造方法呢?答案是 无参的构造方法
第二种情况
@Component
public class UserService {
  public UserService(Student student){
      System.out.println("一个构造参数");
  }
  public UserService(Student student,OrderService orderService){
      System.out.println("两个构造参数");
  }

}
示例3
@Component
public class UserService {
  public UserService(Student student){
      System.out.println("一个构造参数");
  }
}
此时又会用到哪个构造方法呢?肯定就是这个啦
示例4
@Component
public class UserService {
  public UserService(){
   System.out.println("无参构造方法!!");
  }
  public UserService(Student student){
      System.out.println("一个构造参数");
  }
@Autowired
  public UserService(Student student,OrderService orderService){
      System.out.println("两个构造参数");
  }

}
此时会用到哪个构造方法呢? 此时会用到两个参数的构造方法
示例5
@Component
public class UserService {
  public UserService(){
   System.out.println("无参构造方法!!");
  }
  @Autowired
  public UserService(Student student){
      System.out.println("一个构造参数");
  }
   @Autowired(required = false)
  public UserService(Student student,OrderService orderService){
      System.out.println("两个构造参数");
  }

}
此时会用到哪个构造方法呢?答案是 抛出exeception
示例6
@Component
public class UserService {
  public UserService(){
   System.out.println("无参构造方法!!");
  }
  @Autowired(required = false)
  public UserService(Student student){
      System.out.println("一个构造参数");
  }
   @Autowired(required = false)
  public UserService(Student student,OrderService orderService){
      System.out.println("两个构造参数");
  }

}
此时会用到哪个构造方法呢?答案是 两个参数的构造方法
其他的例子就不一一列举了。那么spring是怎样推断的呢?
首先在 
	instanceWrapper = createBeanInstance(beanName, mbd, args);
这个地方断点 并 设置一个condition  beanName.equals("userService")
进入断点后按F7 ,然后F8走到下面的代码时
Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 按F7
按 F8进入下面的for循环
当ibp是AutowiredAnnotationBeanPostProcessor的后置处理时,按F7进入
determineCandidateConstructors
for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
					if (ctors != null) {
						return ctors;
					}
				}
			}
在determineCandidateConstructors这个方法里就是spring推断构造的逻辑,一点都不难,只要你耐心调试,你会发现那几道开胃菜,是so easy。
最主要的代码贴一下。

		for (Constructor candidate : rawCandidates) {
						AnnotationAttributes 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) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						if (ann != null) {
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							boolean required = determineRequiredStatus(ann);
							if (required) {//   @Autowired  默认weiture
							
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							//凡是被@Autowired 注解的都会加入 candidates 
							candidates.add(candidate);
						}
						else if (candidate.getParameterTypes().length == 0) {
							defaultConstructor = candidate;//这个就是看是否有构造方法
						}
					}
======================================
		if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							else if (candidates.size() == 1 && logger.isWarnEnabled()) {
								logger.warn("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[candidates.size()]);
					}
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterTypes().length > 0) {
				//只有一个有参的构造方法
						candidateConstructors = new Constructor[] {rawCandidates[0]};
					}
					else {
						candidateConstructors = new Constructor[0];
					}
注意:这个determineCandidateConstructors是选出构造方法的逻辑,真正要使用哪个构造方法,是开头说的createBeanInstance()方法里的	if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
				//这个 autowireConstructor方法就是推断出到底使用哪个构造方法,大家不         妨点进去看看。一看你就很明了了。
			***return autowireConstructor(beanName, mbd, ctors, args);***
		}

我们这里只是说的注入模型是 AUTOWIRE_NO = 0的情况,还有其他三种注入模型。大家不妨试试。
改变bean的注入模型,我们可以使用一个工厂后置处理器。这里给出一个示例。
@Component
public class MyBeanFactoryPostprocessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    AbstractBeanDefinition beanDefinition= (AbstractBeanDefinition)   beanFactory.getBeanDefinition("userService");
    System.out.println(beanDefinition.getAutowireMode());
    beanDefinition.setAutowireMode(beanFactory.AUTOWIRE_BY_TYPE);

}

}

好了,推断构造方法就讲到这里,不足之处,请大家指出。多多交流,征服spring源码。







你可能感兴趣的:(spring)