依赖注入流程图
- 首先先去找到所有注入点,注入点分为两种: 被@Autowired注解了的属性 以及 被@Autowired注解了的方法
- 遍历每个注入点
- 根据注入点去找Bean,这里如果注解了属性的会根据属性的类型去找Bean,如果注解了的是方法,那就根据方法中的参数类型去找Bean
- 对于找到有几个Bean
- 如果找到一个Bean,直接把这个Bean进行注入
- 如果找到多个Bean,会从多个Bean中确定出一个Bean
- 先判断是不是isAutowiredCandidate
- 再判断是不是复合Qualifier
- 如果还有多个,取@Primary的Bean
- 取出优先级最高的Bean
- 根据名字进行筛选,筛选出唯一的Bean
- 如果是根据属性注入的,那么就是根据属性名字去找
- 如果是根据set方法,那就是参数名字
- 如果没有找到Bean
如果@Autowired的reuqired属性为true,也就是说注入点必须被注入,那么就会报错
依赖注入的方式
对于Spring中依赖注入的方式,分为两种:
- 手动注入
- set方法注入
- 构造方法注入
自动注入
- XML的autowire自动注入
- @Autowired注解的自动注入
手动注入
在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定的值,下面这种底层是通过set方法进行注入
下面这种是通过构造方法进行注入<bean name="userService" class="linc.fun.service.UserService">
<property name="orderService" ref="orderService"/>
</bean>
<bean name="userService" class="linc.fun.service.UserService">
<constructor‐arg index="0" ref="orderService"/>
</bean>
自动注入
自动注入又分为两种
XML的autowire自动注入
-
XML的autowire自动注入
在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:
byType
- byName
- constructor
- default
no
<bean id="userService" class="linc.fun.service.UserService" autowire="byType"/>
如果这么写,表示Spring会自动的给userService中所有的属性进行自动赋值,不需要在属性上加@Autowired注解,但需要这个属性有对应的set方法
PropertyDescriptor对象
在创建Bean的过程中,在填充属性时,Spring会去解析当前类,把当前类的所有方法都解析出来,Spring会解析每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor有几个属性:
public class PropertyDescriptor extends FeatureDescriptor {
private Reference<? extends Class<?>> propertyTypeRef;
private final MethodRef readMethodRef = new MethodRef();
private final MethodRef writeMethodRef = new MethodRef();
private Reference<? extends Class<?>> propertyEditorClassRef;
private boolean bound;
private boolean constrained;
// The base name of the method name which will be prefixed with the
// read and write method. If name == "foo" then the baseName is "Foo"
private String baseName;
private String writeMethodName;
private String readMethodName;
public PropertyDescriptor(String propertyName, Class<?> beanClass)
throws IntrospectionException {
this(propertyName, beanClass,
Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName),
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
}
.....
}
static final String GET_PREFIX = "get";
static final String SET_PREFIX = "set";
static final String IS_PREFIX = "is";
- name: 这个name并不是方法的名字,而是拿方法名字进行过处理后的名字
- 如果方法名字以”get”开头,比如”getXXX”,那么name=XXX
- 如果方法名字以”is”开头,比如”isXXX”,那么name=XXX
- 如果方法名字以”set”开头,比如”setXXX”,那么name=XXX
- readMethodRef: 表示get方法的Method对象的引用
- readMethodName: 表示get方法的名字
- writeMethodRef: 表示set方法的Method对象的引用
- writeMethodName: 表示set方法的名字
- propertyTypeRef: 如果有get方法那么对应的就是返回值的类型,如果set方法那么对应的就是set方法中唯一参数的类型
get,set方法的定义
对于get方法的定义是: 方法参数个数为0,并且方法名字以”get”开头或者方法名字以”is”开头并且方法的返回类型为boolean
对于set方法的定义是: 方法参数个数为1,并且方法以”set”开头并且方法返回类型为voidbyName自动填充属性时的流程
Spring在通过byName的自动填充属性时的流程是:
- 找到所有set方法所对应的XXX部分的名字
-
byType的自动填充属性时的流程
获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取Bean
-
constructor注入
以上,分析了autowire的byType和byName情况,那么接下来分析constructor,constructor表示通过构造方法注入,其实这种情况就比较简单了,没有byType和byName那么复杂
如果是constructor,那么就可以不写set方法了,当某个Bean是通过构造方法来注入时,Spring利用构造方法的参数信息从Spring容器中去找Bean,找到Bean之后作为参数传给构造方法,从而实例化得到一个Bean对象,并完成属性赋值(属性赋值的代码需要程序员来实现)
这里,我们只考虑只有一个有参数构造方法,其实构造方法注入相当于 byType+byName ,普通的byType是根据set方法的参数类型去找Bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找Bean,如果找到多个会根据参数名确定
问:为什么选择使用@Autowired,而不用XML的形式呢?
@Autowired注解相当于XML中的autowire属性的注解方式的替代
官网如下解释: 从本质上将,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine‐grained control and wider applicability
这里强调的是更细粒度的控制
XML中的autowire控制的是整个Bean的所有属性,而@Autowired注解是直接写在某个属性上、某个set方法、某个构造方法上的
倘若我们使用XML的形式,如果用XML中的autowire=constructor,在拥有多个构造方法的情况下,无法进行很好的控制,但是通过@Autowired注解可以直接指定想用哪个构造方法
同时,用@Autowired注解,还可以控制哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制
但是@Autowird无法区分byType和byName,@Autowired是先byType,如果找到多个就会选择byName
那么XML的自动注入底层其实也就是 set方法注入
-
@Autowired注解的自动注入
@Autowired注解是byType+byName的结合
对于@Autowired注解可以有如下几种使用方式 属性上: 先根据属性类型去找Bean,如果找到多个再根据属性名去确定一个
- 构造方法: 现根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个
- set方法上: 先根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个
对于底层到了
- 属性注入
- set方法注入
-
寻找注入点
在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition找出注入点并且缓存
/** * 实例化后的合并BeanDefinition之后的BeanDefinition进行处理 * 找注入点 */ @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }
/** * 寻找注入点,看哪些需要注入,哪些set方法上加了注解 */ private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } // 解析注入点并缓存 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
找注入点的流程
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { // 如果一个Bean的类型是String...,那么则根本不需要进行依赖注入 if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 遍历targetClass中的所有Field ReflectionUtils.doWithLocalFields(targetClass, field -> { // field上是否存在@Autowired、@Value、@Inject中的其中一个 MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { // static filed不是注入点,不会进行自动注入 // 在两个bean都是原型bean的情况下,其中一个是static bean注入,可能导致对象内部属性的值发生变化 if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } // 构造注入点 boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // 遍历targetClass中的所有Method ReflectionUtils.doWithLocalMethods(targetClass, method -> { // 处理桥接方法 泛型的时候,字节码会有两个set方法 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } // method上是否存在@Autowired、@Value、@Inject中的其中一个 MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { // static method不是注入点,不会进行自动注入 if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } // set方法最好有入参,没有就会打印一条日志 if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } // 判断是否是required = true 如果是,但是没找到可以赋值给它就会报错,false就没事 boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); // 父类的会放在最前面 elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); // 找父类的 } while (targetClass != null && targetClass != Object.class); // 返回并且缓存 return InjectionMetadata.forElements(elements, clazz); }
遍历当前类的所有的属性字段field
- 查看字段上是否存在@Autowired、@Value、@Inject中其中任意一个,存在则认为该字段是一个注入点
- 如果字段是static,则不进行注入
- 获取@Autowired中的required属性的值
- 将字段信息构建成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中
- 遍历当前类的所有方法Method
- 判断当前Method是否存在桥接方法,如果是,找到原方法
- 查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点
- 如果方法是static的,则不进行注入
- 获取@Autowired中的required属性的值
- 将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中
- 遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
- 最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并且缓存
static的字段或方法为什么不支持依赖注入
```java @Component @Scope(“prototype”) public class CService { }
@Component @Scope(“prototype”) public class DService { @Autowired private static CService cService;
private void test() {
System.out.println("test...");
}
}
在CService和DService都是原型Bean的情况下,倘若Spring支持static字段进行自动注入,那么现在调用两次
```java
@Test
public void testPrototypeStatic() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
DService d1 = ctx.getBean(DService.class);
DService d2 = ctx.getBean(DService.class);
}
对于此时,d1的CService值是什么?还是它自己注入的值吗
很显然不是,一旦d2创建好了,static Cservice字段的值就发生了改变了,从而会出现bug
桥接方法
// class version 52.0 (52)
// access flags 0x21
// signature Ljava/lang/Object;Llinc/cool/service/UserInterface<Llinc/cool/service/OrderService;>;
// declaration: linc/cool/service/UserService implements linc.cool.service.UserInterface<linc.cool.service.OrderService>
public class linc/cool/service/UserService implements linc/cool/service/UserInterface {
// compiled from: UserService.java
// access flags 0x2
private Llinc/cool/service/OrderService; orderService
// access flags 0x1
public <init>()V
L0
LINENUMBER 10 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public test()V
L0
LINENUMBER 13 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 0
INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC ".test()"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
LINENUMBER 14 L1
RETURN
L2
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
MAXSTACK = 3
MAXLOCALS = 1
// access flags 0x1
public setOrderService(Llinc/cool/service/OrderService;)V
@Lorg/springframework/beans/factory/annotation/Autowired;()
L0
LINENUMBER 22 L0
ALOAD 0
ALOAD 1
PUTFIELD linc/cool/service/UserService.orderService : Llinc/cool/service/OrderService;
L1
LINENUMBER 24 L1
RETURN
L2
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
LOCALVARIABLE orderService Llinc/cool/service/OrderService; L0 L2 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1041 桥接方法
public synthetic bridge setOrderService(Ljava/lang/Object;)V
@Lorg/springframework/beans/factory/annotation/Autowired;()
L0
LINENUMBER 10 L0
ALOAD 0
ALOAD 1
CHECKCAST linc/cool/service/OrderService
INVOKEVIRTUAL linc/cool/service/UserService.setOrderService (Llinc/cool/service/OrderService;)V
RETURN
L1
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 2
}
可以看到UserService的字节码中有两个setOrderService方法
public setOrderService(Llinc/cool/service/OrderService;)V
public synthetic bridge setOrderService(Ljava/lang/Object;)V
并且都是存在@Autowired注解的,所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法
注入点进行注入
Spring在AutowiredAnnotationBeanPostProcessor#postProcessProperties方法中,会遍历所找到的注入点依次进行注入
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 找注入点(所有被@Autowired注解了的Field或Method) 此时已经可以直接从缓存中拿出来了
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 给字段赋值,给方法参数赋值
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
/**
* 注入
*/
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍历每个注入点进行依赖注入
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
字段注入
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
...
/**
* 字段的注入
*/
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 这里没有进行判断Pvs有没有,和method有点区别
Field field = (Field) this.member;
Object value;
if (this.cached) {
// 对于原型Bean,第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true
// 第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为true,也就进到此处了
// 注入点内并没有缓存被注入的具体Bean对象,而是beanName,这样就能保证注入到不同的原型Bean对象
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
} catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
} else {
// 根据filed从BeanFactory中查到的匹配的Bean对象
value = resolveFieldValue(field, bean, beanName);
}
// 反射给filed赋值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
// 注册一下beanName依赖了autowiredBeanNames,
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象 (考虑原型bean)
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
- 遍历所有的AutowiredFieldElement对象
- 将对应的字段封装为DependencyDescriptor对象
- 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象
- 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortCutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该对象时,就可以拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
-
Set方法注入
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement { ... @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 如果pvs中已经有当前注入点的值了,则跳过注入 看属性描述器中对应属性的名字在不在pvs里,在就跳过 if (checkPropertySkipping(pvs)) { return; } Method method = (Method) this.member; Object[] arguments; // 找值的 // 第一次注入是没有缓存的 if (this.cached) { try { arguments = resolveCachedArguments(beanName); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve arguments = resolveMethodArguments(method, bean, beanName); } } else { arguments = resolveMethodArguments(method, bean, beanName); } if (arguments != null) { try { ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } }
@Nullable private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String b // 方法参数个数 int argumentCount = method.getParameterCount(); // 保存参数对应的Bean对象 Object[] arguments = new Object[argumentCount]; // 有几个方法参数就有几个依赖描述器 DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount]; Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); // 遍历每个方法参数,找到匹配的bean对象 for (int i = 0; i < arguments.length; i++) { MethodParameter methodParam = new MethodParameter(method, i); // this.required: 是不是一定要赋值 DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.req currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBe if (arg == null && !this.required) { arguments = null; break; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoin } } synchronized (this) { if (!this.cached) { if (arguments != null) { DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descripto registerDependentBeans(beanName, autowiredBeans); if (autowiredBeans.size() == argumentCount) { Iterator<String> it = autowiredBeans.iterator(); Class<?>[] paramTypes = method.getParameterTypes(); for (int i = 0; i < paramTypes.length; i++) { String autowiredBeanName = it.next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, paramTypes[ cachedMethodArguments[i] = new ShortcutDependencyDescripto descriptors[i], autowiredBeanName, paramTypes[i]); } } } this.cachedMethodArguments = cachedMethodArguments; } else { this.cachedMethodArguments = null; } this.cached = true; } } return arguments; }
遍历所有的AutowiredMethodElement对象
- 遍历将对应的方法的参数,将每个参数封装成MethodParameter对象
- 将MethodParameter对象封装成DependencyDescriptor对象
- 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,摘到当前方法参数所匹配的Bean对象
- 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建对象时,就可以直接拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
- 利用反射将找到的所有结果对象传给当前方法,并且执行
注入点注入流程
BeanFactory#resolveDependency
该方法表示,传入一个依赖描述DependencyDescriptor,该方法会根据依赖描述从BeanFactory中找出对应的唯一的一个Bean对象@Nullable Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
我们可以分析一下BeanFactory的实现类DefaultListableBeanFactory#resolveDependency方法的具体实现Spring中根据类型找Bean的底层流程
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable St @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typ // 用来获取方法入参名字的 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); // 所需要的类型是Optional if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } // 所需要的的类型是ObjectFactory,或ObjectProvider else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory().createDependencyProvider(descriptor, reque } else { // 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean Object result = getAutowireCandidateResolver().getLazyResolutionProxy descriptor, requestingBeanName); if (result == null) { // descriptor表示某个属性或某个set方法 // requestingBeanName表示正在进行依赖注入的Bean result = doResolveDependency(descriptor, requestingBeanName, auto } return result; } }
```javapublic Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansExce InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { // 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存 Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } Class<?> type = descriptor.getDependencyType(); // 获取@Value所指定的值 看方法参数,字段名有没有 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { // 占位符填充(${}) String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); // 解析Spring表达式(#{}) value = evaluateBeanDefinitionString(strVal, bd); } // 将value转化为descriptor所对应的类型 如果想让123赋值给一个对象,默认是做不了的,需要类型转换器 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { // A custom TypeConverter which does not support TypeDescriptor resolution... return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } } // 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConvert if (multipleBeans != null) { return multipleBeans; } // 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass --> 比较核心 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); // 找到的Bean是空的->expected at least 1 bean which qualifies as autowire candidate if (matchingBeans.isEmpty()) { // required为true,抛异常 if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; // 找到了多个 if (matchingBeans.size() > 1) { // 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); } else { // In case of an optional Collection/Map, silently ignore a non-unique case: // possibly it was meant to be an empty collection of multiple regular beans // (before 4.3 in particular when we didn't even look for collection beans). return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // 只有一个 // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } // 记录匹配过的beanName if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } // 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; // @Bean的时候返回的是null,最后放到单例池的是NullBean if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass( } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanNam
@Nullable Set