思路分析
Spring中的一个bean,需要实例化得到一个对象,而实例化就需要用到构造方法。 一般情况下,一个类只有一个构造方法:要么是无参的构造方法,要么是有参的构造方法。
如果只有一个无参的构造方法,那么实例化就只能使用这个构造方法了。如果只有一个有参的构造方法,那么实例化时能使用这个构造方法吗?
要分情况讨论:
1.使用AnnotationConfigApplicationContext,会使用这个构造方法进行实例化,那么Spring会根据构造方法的参数信息去寻找bean,然后传给构造方法
2.使用ClassPathXmlApplicationContext,表示使用XML的方式来使用bean,要么在XML中指定构造方法的参数值(手动指定),要么配置autowire=constructor让Spring自动去寻找bean做为构造方法参数值。
上面是只有一个构造方法的情况,那么如果有多个构造方法呢? 又分为两种情况,多个构造方法中存不存在无参的构造方法。
分析:一个类存在多个构造方法,那么Spring进行实例化之前,该如何去确定到底用哪个构造方法呢?
- 如果开发者指定了想要使用的构造方法,那么就用这个构造方法
- 如果开发者没有指定想要使用的构造方法,则看开发者有没有让Spring自动去选择构造方法
- 如果开发者也没有让Spring自动去选择构造方法,则Spring利用无参构造方法,如果没有无参构造方法,则报错
针对第一点,开发者可以通过什么方式来指定使用哪个构造方法呢?
1. xml中的<constructor-arg>标签,这个标签表示构造方法参数,所以可以根据这个确定想要使用的构造方法的参数个数,从而确定想要使用的构造方法
<bean id="orderService" class="com.spring.OrderService"/>
<bean id="productService" class="com.spring.ProductService"/>
<bean id="userService" class="com.spring.UserService">
<constructor-arg index="0" ref="orderService"/>
<constructor-arg index="1" ref="productService"/>
</bean>
2. 通过@Autowired注解,@Autowired注解可以写在构造方法上,所以哪个构造方法上写了@Autowired注解,表示开发者想使用哪个构造方法,当然,它和第一个方式的不同点是,通过xml的方式,我们直接指定了构造方法的参数值,而通过@Autowired注解的方式,需要Spring通过byType+byName的方式去找到符合条件的bean作为构造方法的参数值
@Component
public class UserService {
private OrderService orderService;
private ProductService productService;
public UserService() {
System.out.println(0);
}
@Autowired
public UserService(OrderService orderService, ProductService productService) {
System.out.println(2);
this.orderService = orderService;
this.productService = productService;
}
}
再来看第二点,如果开发者没有指定想要使用的构造方法,则看开发者有没有让Spring自动去选择构造方法,对于这一点,只能用在ClassPathXmlApplicationContext,因为通过AnnotationConfigApplicationContext 没有办法去指定某个bean可以自动去选择构造方法,而通过ClassPathXmlApplicationContext 可以在xml中指定某个bean的autowire为constructor,虽然这个属性表示通过构造方法自动注入,所以需要自动的去选择一个构造方法进行自动注入,因为是构造方法,所以顺便是进行实例化。
<bean id="userService" class="com.spring.UserService" autowire="constructor"/>
当然,还有一种情况,就是多个构造方法上写了@Autowired注解,那么此时Spring会报错。
但是,因为@Autowired还有一个属性required,默认为ture,所以一个类中,只有能一个构造方法标注了@Autowired或@Autowired(required=true),有多个会报错。但是可以有多个@Autowired(required=false),这种情况下,需要Spring从这些构造方法中去自动选择一个构造方法。
思路总结
1、 默认情况,用无参构造方法,或者只有一个构造方法就用那一个。
2、 程序员指定了构造方法入参值,通过getBean()或者BeanDefinition.getConstructorArgumentValues()指定,那就用所匹配的构造方法。
3、 程序员想让Spring自动选择构造方法以及构造方法的入参值, autowire = "constructor"。
4、 程序员通过@Autowired注解指定了某个构造方法,但是希望Spring自动找该构造方法的入参值。
源码剖析
createBeanInstance
AbstractAutowireCapableBeanFactory类中的createBeanInstance()方法会去创建一个Bean实例,其中Object[] args 就是调用getObject()方法传入的args参数。
// 创建Bean实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 拿到Bean的Class对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 不是public的且不可访问 则抛异常
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException();
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName, mbd);
}
// @Bean对应的BeanDefinition
// 创建@Bean定义的Bean对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 一个原型的BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来
// 避免每次都要进行构造方法推断
boolean resolved = false; // 标识是否已经解析出要执行的构造方法
boolean autowireNecessary = false; // 标识是否需要对构造方法的参数进行依赖注入
// 没有明确指定构造方法参数
// 在getBean()方法时指定了args时 不考虑缓存
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// resolvedConstructorOrFactoryMethod 是缓存的构造方法Constructor对象
// 有缓存构造方法或工厂方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// 表示有没有必要进行注入,比如当前BeanDefinition用的无参构造,那么autowireNecessary = false
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 构造方法已经确定
if (resolved) {
// 需要对构造方法参数进行依赖注入(构造方法注入)
if (autowireNecessary) {
// 方法内会拿到缓存好的构造方法入参
return autowireConstructor(beanName, mbd, null, null);
// 不需要对构造方法参数进行依赖注入
} else {
// 表示用的是默认的无参构造方法,直接进行实例化
return instantiateBean(beanName, mbd);
}
}
// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中哪个构造方法
// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// ctors = null有两种情况:1.只有一个无参构造;2.有多个构造方法
// 条件1:ctors != null,说明有加了@Autowired的 构造方法
// 条件2:bean的自动注入模式是 AUTOWIRE_CONSTRUCTOR
// 条件3:BeanDefinition中添加了构造方法的参数和值
// 条件4:调用getBean()方法时传入了args参数
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造方法注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 以上情况都不匹配,则使用无参构造方法
// 若没有无参构造,则报错
return instantiateBean(beanName, mbd);
}
createBeanInstance主要过程:
- 根据BeanDefinition加载类得到Class对象;
- 如果BeanDefinition绑定了一个Supplier,那就调用Supplier的get方法得到一个对象并直接返回;
- 如果BeanDefinition中存在factoryMethodName,也就是通过@Bean定义的bean对象,那么就调用该工厂方法得到一个bean对象并返回;
- 如果BeanDefinition已经自动构造过了,那就调用autowireConstructor()自动构造一个对象
- 调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法得到哪些构造方法是可以用的;
- 如果存在可用得构造方法,或者当前BeanDefinition的autowired是AUTOWIRE_CONSTRUCTOR,或者BeanDefinition中指定了构造方法参数值,或者创建Bean的时候指定了构造方法参数值,那么就调用autowireConstructor()方法自动构造一个对象;
- 最后,如果不是上述情况,就根据无参的构造方法实例化一个对象。
determineCandidateConstructors
// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中哪个构造方法
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
return null;
}
AutowiredAnnotationBeanPostProcessor 实现了SmartInstantiationAwareBeanPostProcessor的 determineCandidateConstructors()方法,会把加了@Autowired注解的构造方法找出来。
// 推断候选者构造方法
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException {
checkLookupMethods(beanClass, beanName);
// Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
// 先从缓存中找
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
// 缓存中没有
if (candidateConstructors == null) {
// 加锁
synchronized (this.candidateConstructorsCache) {
// 再次从缓存中找 DCL
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
// 缓存中还是没有
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
// 拿到本类中所有的构造方法,包括public、protected、default、privite的
// 如果beanClass表示接口、基元类型、数组或 void,则返回长度为0的数组。
rawCandidates = beanClass.getDeclaredConstructors();
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
// 记录required为true的构造方法,一个类中只能有一个required为true的构造方法
Constructor<?> requiredConstructor = null;
// 记录默认的无参构造方法
Constructor<?> defaultConstructor = null;
// 遍历所有的构造方法
for (Constructor<?> candidate : rawCandidates) {
// 当前构造方法是否有@Autowired注解
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
// ann == null,说明当前构造方法上没有@Autowired注解
if (ann == null) {
// 如果当前是代理类,则得到被代理类的类型
Class<?> userClass = ClassUtils.getUserClass(beanClass);
// userClass != beanClass,说明当前类是代理类
if (userClass != beanClass) {
// 被代理类的构造方法上是否有@Autowired注解
Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
}
// 当前构造方法上有@Autowired注解
if (ann != null) {
// 整个类中如果已经有了一个required为true的构造方法,那就不能再有其他加了@Autowired的构造方法
if (requiredConstructor != null) {
throw new BeanCreationException();
}
// @Autowired的required属性值
boolean required = determineRequiredStatus(ann);
// 如果required = true
if (required) {
// 如果还有其他构造方法有@Autowired则报错
if (!candidates.isEmpty()) {
throw new BeanCreationException();
}
// 当前构造方法为required为true的构造方法
requiredConstructor = candidate;
}
// 记录所有加了@Autowired的构造方法,不管是required是true还是false
// 如果默认无参的构造方法上也加了@Autowired,也会加入到candidates中
candidates.add(candidate);
// 当前构造方法上没有@Autowired注解且是无参构造方法
// 那么该构造方法就是默认的无参构造方法
} else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
// 有可能存在有参、并且没有添加@Autowired的构造方法
}
// 有加了@Autowired的构造方法
// 要么有多个required = false构造方法,要么只有一个required = true的构造方法
if (!candidates.isEmpty()) {
// 没有required = true的构造方法,则都是required = false构造方法
if (requiredConstructor == null) {
// 如果有无参构造方法,则将无参构造方法加入到候选者集合
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
// 没有加了@Autowired的构造方法
// 只有一个有参构造方法
} else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[]{rawCandidates[0]};
} else {
// 没有加了@Autowired的构造方法,且有多个有参构造或一个无参构造,则返回空
candidateConstructors = new Constructor<?>[0];
}
// 将推断出来的候选者构造方法放入缓存
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
AutowiredAnnotationBeanPostProcessor 推断构造方法的主要过程:
主要分两种情况
- 不存在加了@Autowired的构造方法:
- 若只有一个有参构造方法,则返回此构造方法;
- 若有多个构造方法,返回null;
- 若只有一个无参构造方法,返回null。
- 存在加了@Autowired的构造方法:
- 若只有一个required = true的构造方法,则返回此构造方法;
- 若有多个required = true的构造方法,则抛异常;
- 若有一个required = true的构造方法和其他required = false的构造方法,则抛异常;
- 没有required = true的构造方法,则返回required = false的构造方法以及无参构造方法 。
autowireConstructor
// 从chosenCtors中选择要使用的构造方法
// explicitArgs: getBean()方法传入的args
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null; // 记录选中构造方法
ArgumentsHolder argsHolderToUse = null; // 记录构造方法参数
Object[] argsToUse = null;
//如果getBean()传入了args,则构造方法要使用的入参就已经确定好了
if (explicitArgs != null) {
argsToUse = explicitArgs;
} else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 拿到指定或缓存的构造方法
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// 缓存的构造方法参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new RuntimeBeanReference("orderService"));
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new RuntimeBeanReference("orderService"));
// 解析RuntimeBeanReference,到容器中查找名称为orderService的Bean对象
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
// 没有确定要使用的构造方法,或者确定了构造方法但是方法入参没有确定
if (constructorToUse == null || argsToUse == null) {
// 传入的候选构造方法
Constructor<?>[] candidates = chosenCtors;
// 没有传入候选的构造方法,则拿到类中所有的构造方法
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
// 如果只有一个候选构造方法,并且没有指定要使用构造方法参数值,并且该构造方法是无参的,
// 也就是只有一个无参构造,那就直接用这个无参构造方法进行实例化了
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
// 缓存构造方法和构造参数
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 根据构造方法uniqueCandidate、构造参数 实例化对象
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// 是否需要对构造方法参数进行依赖注入
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
// 确定要选择的构造方法参数个数的最小值,后续判断候选构造方法的参数如果小于minNrOfArgs,则直接pass掉
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
} else {
// 如果通过BeanDefinition传入了构造方法参数值,因为有可能通过下标指定了
// 比如0位置有值,2位置有值,虽然只指定了两个值,但是构造方法需要的参数个数最小值是3
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 处理RuntimeBeanReference
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 对候选构造方法进行排序,public的方法排在最前面,都是public的情况下参数个数越多越靠前
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
// 参数个数相同且得分也相同的构造方法
Set<Constructor<?>> ambiguousConstructors = null;
// 记录通过参数找不到对应的Bean而抛出的异常
Deque<UnsatisfiedDependencyException> causes = null;
// 遍历每个构造方法,进行筛选
for (Constructor<?> candidate : candidates) {
// 构造方法参数个数
int parameterCount = candidate.getParameterCount();
// 本次遍历时,以前已经选出来的所要用的构造方法和入参对象,并且入参对象个数比当前这个构造方法的参数个数多,则不用再遍历了
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
break;
}
// 参数个数小于所要求的参数个数,则不会考虑该构造方法
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
// 构造方法参数类型
Class<?>[] paramTypes = candidate.getParameterTypes();
// 没有通过getBean()所指定构成方法参数值
if (resolvedValues != null) {
try {
String[] paramNames = null;
if (resolvedValues.containsNamedArgument()) {
// 如果在构造方法上使用了@ConstructorProperties,那么就直接取定义的值作为构造方法的参数名
paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
// 获取参数名解析器
// StandardReflectionParameterNameDiscoverer: 通过反射(1.8)获取方法参数名称
// LocalVariableTableParameterNameDiscoverer: 解析字节码本地变量表获得方法参数名称
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 解析方法参数名
paramNames = pnd.getParameterNames(candidate);
}
}
}
// 根据参数类型和参数名,找到对应的Bean对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
} catch (UnsatisfiedDependencyException ex) {
// 如果通过参数找不到对应的Bean而抛异常,则先记录异常
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
} else {
// 没有通过BeanDefinition的指定构造方法参数值,但是在调用getBean方法时传入了参数值,那就表示只能用对应参数个数的构造方法
if (parameterCount != explicitArgs.length) {
continue;
}
// 不用再去BeanFactory中去查找Bean对象了,已经有了,同时当前正在遍历的构造方法就是可用的构造方法
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 当前遍历的构造方法所需要的入参对象都找到了,根据参数类型和找到的参数对象计算出一个匹配值,值越小越匹配
// 默认为Lenient,表示宽松模式
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 值越小越匹配
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
// 值相等的情况下,记录一下匹配值相同的构造方法
} else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
// 如果没有可用的构造方法,就取记录的最后一个异常并抛出
if (constructorToUse == null) {
// 有构造方法 通过参数找不到对应的Bean而抛出异常
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
// 记录压制的异常
this.beanFactory.onSuppressedException(cause);
}
// 把异常抛出
throw ex;
}
throw new BeanCreationException();
// 有多个可用的构造方法且分数一样,并且不是宽松模式,则抛异常
} else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException();
}
// 不是通过getBean()方法指定args,且找到了构造方法已经要用的入参对象,则缓存
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
// 根据找到的构造方法和方法入参实例化对象,并将实例化的对象赋值给bw
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
- 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化
- 如果没有确定的构造方法或构造方法参数值,那么
- 如果没有候选的构造方法(chosenCtors = null),那么则找出类中所有的构造方法;
- 如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化;
- 说明有多个可用的构造方法或者当前Bean需要自动通过构造方法注入;
- 计算minNrOfArgs的值,根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数;
- 对所有的构造方法进行排序,public的方法排在最前面,都是public的情况下参数个数越多越靠前;
- 遍历每个构造方法,构造方法参数个数小于minNrOfArgs,则忽略该构造方法;
- 如果调用getBean()方法时没有指定构造方法参数值,则先通过ParameterNameDiscoverer解析出参数名,然后根据参数类型和参数名称从容器中找到对应的Bean对象;
- 如果调用getBean()方法时指定了构造方法参数值,那么就直接利用这些值;
- 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的;
- 默认采用Lenient宽松模式
- 构造方法参数类型和找到的Bean对象完全匹配,得0分;
- 构造方法参数类型是是找到的Bean对象的父类,得2分;
- 构造方法参数类型是找到的Bean对象实现的接口,得1分;
- 最后计算出得分,得分越小的越匹配。
- 遍历完所有构造方法,若没有找到可用的构造方法,则抛出异常;
- 缓存推断出来的构造方法。
- 根据找到的构造方法和方法入参实例化对象。
@Bean的情况
首先,Spring会把@Bean修饰的方法解析成BeanDefinition:
- 如果方法不是static的,那么解析出来的BeanDefinition中:
- factoryBeanName为AppConfig所对应的beanName,比如"appConfig"
- factoryMethodName为对应的方法名,比如"userService"
- factoryClass为AppConfig.class
- 如果方法是static的,那么解析出来的BeanDefinition中:
- factoryBeanName为 null
- factoryMethodName为对应的方法名,比如"userService"
- factoryClass也为AppConfig.class
这和早期xml通过静态工厂定义Bean对象和实例工厂定义Bean对象的方式相匹配
<bean id="userService" factory-bean="appConfig" factory-method="creatUserService"/>
<bean id="userService" class="com.spring.AppConfig" factory-method="creatUserService"/>
instantiateUsingFactoryMethod
instantiateUsingFactoryMethod方法就是处理通过@Bean注解定义的Bean对象,其中确定FactoryMethod方法和方法所需参数的逻辑与autowireConstructor的逻辑大致相同。
public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
// 这里拿到的是factoryBeanName,而不是factoryMethodName,也就是@Bean所在类对象名称
// 例如 appConfig
String factoryBeanName = mbd.getFactoryBeanName();
// factoryBeanName不为null的情况,对应@Bean标注的方法不是staic方法
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException();
}
// 这里拿到的factoryBean为AppConfig的代理对象
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
// 注册Bean对象之间的依赖关系
this.beanFactory.registerDependentBean(factoryBeanName, beanName);
// 这里拿到的factoryClass为AppConfig的代理对象的class
factoryClass = factoryBean.getClass();
isStatic = false;
// factoryBeanName为null的情况,对应@Bean标注的方法是staic方法
} else {
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
// 通过以上步骤确定了 factoryBean、factoryClass和isStatic的值
// 接下来就是确定要使用哪个factoryMethod以及factoryMethod所需要的参数
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// 如果getBean()传入了args,则构造方法要使用的入参就已经确定好了
if (explicitArgs != null) {
argsToUse = explicitArgs;
} else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 拿到指定或缓存的FactoryMethod
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// 缓存的构造方法参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new RuntimeBeanReference("orderService"));
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new RuntimeBeanReference("orderService"));
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
}
}
// 没有确定要使用的factoryMethod,或者确定了factoryMethod但是方法入参没有确定
if (factoryMethodToUse == null || argsToUse == null) {
// 拿到代理对象的目标对象 即AppConfig.class
factoryClass = ClassUtils.getUserClass(factoryClass);
// 记录所有的候选方法集合
List<Method> candidates = null;
// 只有一个FactoryMethod,则就使用这个唯一的FactoryMethod
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
candidates = new ArrayList<>();
// 拿到类中所有的方法,包括继承的方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
// 筛选出满足条件的FactoryMethod
for (Method candidate : rawCandidates) {
if ((!isStatic || isStaticCandidate(candidate, factoryClass)) && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
// 如果筛选之后,只有一个可用的FactoryMethod,且不是通过getBean()指定args,且方法是无参的,则就使用该FactoryMethod了
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// 如果筛选过后还有多个可用的FactoryMethod
if (candidates.size() > 1) {
// 则将FactoryMethod进行排序,public的方法排在最前面,都是public的情况下参数个数越多越靠前
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}
ConstructorArgumentValues resolvedValues = null;
// 默认为true
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
// 计算 minNrOfArgs 第一次为0
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
} else {
if (mbd.hasConstructorArgumentValues()) {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
} else {
minNrOfArgs = 0;
}
}
Deque<UnsatisfiedDependencyException> causes = null;
// 遍历所有的FactoryMethod
for (Method candidate : candidates) {
// 方法参数
int parameterCount = candidate.getParameterCount();
if (parameterCount >= minNrOfArgs) {
ArgumentsHolder argsHolder;
// 拿到所有参数的类型
Class<?>[] paramTypes = candidate.getParameterTypes();
if (explicitArgs != null) {
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
} else {
try {
String[] paramNames = null;
if (resolvedValues != null && resolvedValues.containsNamedArgument()) {
// 获取参数名解析器
// StandardReflectionParameterNameDiscoverer: 通过反射(1.8)获取方法参数名称
// LocalVariableTableParameterNameDiscoverer: 解析字节码本地变量表获得方法参数名称
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 解析参数名
paramNames = pnd.getParameterNames(candidate);
}
}
// 根据参数类型和参数名,找到对应的Bean对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
} catch (UnsatisfiedDependencyException ex) {
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
// 当前遍历的构造方法所需要的入参对象都找到了,根据参数类型和找到的参数对象计算出一个匹配值,值越小越匹配
// 默认为严格模式
int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 值越小越匹配
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
// 计算的值和已有的factoryMethod值相等,且是严格模式的计算方式,且参数个数也相同,且参数类型不相同
} else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight && !mbd.isLenientConstructorResolution() && paramTypes.length == factoryMethodToUse.getParameterCount() && !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
// 则将这两个factoryMethod加入集合,再用其他方式选择
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
// 没有确定要使用的factoryMethod,或者确定了factoryMethod但是方法入参没有确定
if (factoryMethodToUse == null || argsToUse == null) {
// 根据factoryMethod方法参数依赖查找时有报错
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
// factoryMethod的返回值是void
} else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException();
// 有多个相同的FactoryMethod
} else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException();
}
// 不是调用getBean()方法指定的args的方式
// 则缓存解析到的factoryMethod以及所需要的参数
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}