前面介绍了@Bean标记的方法如何注册为BeanDefinition,有了 BeanDefinition 后,就能根据其中的信息实例化一个对象
在@Bean的BeanDefinition有几个比较重要的属性,一个是 factoryMethodName,一个是 factoryBeanName
factoryMethodName可以表示该Bean是一个@Bean,而factoryBeanName可以知道该Bean应该由谁来创建
其实到这基本就能猜测到@Bean如何实例化,无非是根据factoryBeanName找到对应的配置类,比如AppConfig,有了配置类后,又可以根据factoryMethodName知道对应的方法,那么调用一下就可以了
但过程还是挺复杂的,下面分析下源码
实例化过程在 AbstractAutowireCapableBeanFactory#createBeanInstance
其中有一步就是专门处理@Bean,由上面分析我们知道@Bean的Beandefinition会设置一个 factoryMethodName ,根据这个就可以判断是不是@bean
createBeanInstance
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
使用ConstructorResolver去是实例化,进入分析
public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
// 设置一些类型转换器等
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
// 这里拿到的是配置类的名字,在加载@Bean源码分析中已经知道了,如果不是静态的方法,就会有factoryBeanName
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
// 拿到配置类的Bean,这里并不是拿@Bean的Bean
factoryBean = this.beanFactory.getBean(factoryBeanName);
// 注册依赖Bean,表示@Bean依赖于配置类的Bean
this.beanFactory.registerDependentBean(factoryBeanName, beanName);
factoryClass = factoryBean.getClass();
isStatic = false;
} else {
// 如果factoryBeanName为空,表示这个@Bean标记的方法是一个静态的方法
factoryBean = null;
factoryClass = mbd.getBeanClass(); //拿到的是配置类的Class
isStatic = true;
}
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// 省略了一些基本不走的逻辑...
if (factoryMethodToUse == null || argsToUse == null) {
factoryClass = ClassUtils.getUserClass(factoryClass); // 可能是jdk的代理对象,拿到真实的class
List<Method> candidates = null;
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod(); // 这里可能受其它逻辑影响,以及解析过了,就会把Method设置到factoryMethodToIntrospect属性
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
// 前面没有解析过
candidates = new ArrayList<>();
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd); // 找出该配置类factoryClass的所有方法
for (Method candidate : rawCandidates) {
// 修饰类型一样,方法名一样,这里也有可能会找到多个重载
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
// @Bean没有重载并且getBean也没有传入参数
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0); // 只有一个方法取出
if (uniqueCandidate.getParameterCount() == 0) { // 该@Bean方法没有参数
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 大部分其实都是走这里 instantiate就是通过反射调用uniqueCandidate返回一个对象,然后设置到BeanWrapper返回
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
if (candidates.size() > 1) {
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR); // 找到了多个@Bean名字一样的,参数越多的排在前面
}
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 评分
int minTypeDiffWeight = Integer.MAX_VALUE;
// 模棱两可的@Bean,意思就是有多个@Bean,并且推断不出用哪个,是要抛出异常的
Set<Method> ambiguousFactoryMethods = null;
// minNrOfArgs 普通情况为0,如果指定了参数,那么就是参数的个数,或者BeanDefinition指定了构造方法参数值,那么就是这里面的长度
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;
for (Method candidate : candidates) {
// 参数数量
int parameterCount = candidate.getParameterCount();
if (parameterCount >= minNrOfArgs) {
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes(); // 参数类型
if (explicitArgs != null) {
// 这里的逻辑是显示的传入参数,例如getBean("bean",arg1,arg2) ,没有匹配上继续匹配下一个
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
try {
// 没有指定参数的情况下
String[] paramNames = null;
// 找出参数名称,反射 & 本地变量表
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
// 根据BeanDefinition中定义的参数,以及通过name从beanFactory获取到Bean
// 最终组成为argsHolder ,这里面的详细过程后面文章讲
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) {
// 如果根据当前的方法参数计算出来的评分更小些,那么应该使用该方法来创建Bean
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null; // 同时也就不存在模棱两可的方法了
}
// 如果评分一样的,那么表示推断不出使用哪个方法构造Bean,最终找不出来要抛异常
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
if (factoryMethodToUse == null || argsToUse == null) {
// 表示没有找到
// 看有没有记录到异常,有抛出
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
// ...省略,就是要抛异常
}
else if (void.class == factoryMethodToUse.getReturnType()) {
// 返回值是void,不正常,抛出异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() + "' on class [" +
factoryClass.getName() + "]: needs to have a non-void return type!");
}
else if (ambiguousFactoryMethods != null) {
// 表示推断不出使用哪个方法构造Bean,抛异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found on class [" + factoryClass.getName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}
if (explicitArgs == null && argsHolderToUse != null) {
// 找到了,缓存起来
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
// 通过反射调用uniqueCandidate返回一个对象,然后设置到BeanWrapper返回
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
以上便是@Bean的关键逻辑,根据修饰符以及方法名称找到对于的方法,可能因为重载方法有多个,这个时候如果制定了参数,那么直接根据指定的参数匹配方法,如果没有指定参数,那么spring会根据评分算法帮我们找出方法
至于其中的方法评分的算法,不是重点,大概就是说匹配成都越高的分越低,分越低就优先级越高,如果匹配度不高那么是要加分的,比如当前类型是值的类型的父类,加两分,当前类型是个接口加一分
关于这个算法,后面出文章讲解
欢迎关注,学习不迷路!