> 文档中心 > Spring之依赖注入底层源码解析(二)

Spring之依赖注入底层源码解析(二)


Spring之依赖注入底层源码解析

  • BeanFactory#resolveDependency
    • Spring中根据类型找Bean的底层流程
  • DefaultListableBeanFactory#findAutowireCandidates
    • Spring中根据类型找beanName底层流程
  • 依赖注入流程
  • @Qualifier使用
  • @Resource注解底层工作流程

BeanFactory#resolveDependency

@NullableObject resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;

该方法表示,传入一个依赖描述DependencyDescriptor,该方法会根据依赖描述从BeanFactory中找出对应的唯一的一个Bean对象

我们可以分析一下BeanFactory的实现类DefaultListableBeanFactory#resolveDependency方法的具体实现

Spring中根据类型找Bean的底层流程

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable St@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typ// 用来获取方法入参名字的descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());// 所需要的类型是Optionalif (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}// 所需要的的类型是ObjectFactory,或ObjectProviderelse 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注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选BeanObject result = getAutowireCandidateResolver().getLazyResolutionProxydescriptor, requestingBeanName);if (result == null) {// descriptor表示某个属性或某个set方法// requestingBeanName表示正在进行依赖注入的Beanresult = doResolveDependency(descriptor, requestingBeanName, auto}return result;}}     
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansExceInjectionPoint 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, typeConvertif (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 candidateif (matchingBeans.isEmpty()) {// required为true,抛异常if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;// 找到了多个if (matchingBeans.size() > 1) {// 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->nameautowiredBeanName = 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();}// 记录匹配过的beanNameif (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}// 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBeanif (instanceCandidate instanceof Class) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;// @Bean的时候返回的是null,最后放到单例池的是NullBeanif (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);}}
 @Nullableprivate Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanNam@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {Class<?> type = descriptor.getDependencyType();if (descriptor instanceof StreamDependencyDescriptor) {// 找到type所匹配的所有beanMap<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptorif (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}// 构造成一个streamStream<Object> stream = matchingBeans.keySet().stream().map(name -> descriptor.resolveCandidate(name, type, this)).filter(bean -> !(bean instanceof NullBean));// 排序if (((StreamDependencyDescriptor) descriptor).isOrdered()) {stream = stream.sorted(adaptOrderComparator(matchingBeans));}return stream;}else if (type.isArray()) {// 得到数组元素的类型Class<?> componentType = type.getComponentType();ResolvableType resolvableType = descriptor.getResolvableType();Class<?> resolvedArrayType = resolvableType.resolve(type);if (resolvedArrayType != type) {componentType = resolvableType.getComponentType().resolve();}if (componentType == null) {return null;}// 根据数组元素类型找到所匹配的所有BeanMap<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,new MultiElementDescriptor(descriptor));if (matchingBeans.isEmpty()) {return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}// 进行类型转化TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayTypif (result instanceof Object[]) {Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);if (comparator != null) {Arrays.sort((Object[]) result, comparator);}}return result;}else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric()if (elementType == null) {return null;}Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,new MultiElementDescriptor(descriptor));if (matchingBeans.isEmpty()) {return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()Object result = converter.convertIfNecessary(matchingBeans.values(), type);if (result instanceof List) {if (((List<?>) result).size() > 1) {Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);if (comparator != null) {((List<?>) result).sort(comparator);}}}return result;}else if (Map.class == type) {ResolvableType mapType = descriptor.getResolvableType().asMap();Class<?> keyType = mapType.resolveGeneric(0);// 如果Map的key不是Stringif (String.class != keyType) {return null;}Class<?> valueType = mapType.resolveGeneric(1);if (valueType == null) {return null;}Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,new MultiElementDescriptor(descriptor));if (matchingBeans.isEmpty()) {return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}return matchingBeans;}else {return null;}}   

Spring之依赖注入底层源码解析(二)

  1. 调用DefaultListableBeanFactory#resolveDependency

    1. 判断依赖的类型

      1. 如果是Optional,调用doResolveDependency

      2. 如果是ObjectFactory或ObjectProvider,在调用ObjectFactory#getObject方法时调用doResolveDependency

      3. 如果依赖上有@Lazy注解.那么就会生成一个代理对象然后返回,那么在调用代理对象中的方法时调用doResolveDependency

  2. 对于上面的doResolveDependency执行逻辑如下

    1. 判断是否存在@Value注解
      1. 如果存在,获取并且解析descriptor上的@Value注解,进行解析后并且返回
      2. 判断descriptor的类型
        1. 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的方法不用进一步做筛选了
        2. 调用findAutowireCandidate,findAutowireCandidate该方法会返回一个Map,表示会根据类型去找Bean,Map的key为beanName,Map的value为对象,对于value可能是Bean对象也可能是某Bean的class对象,因为该方法只负责根据类型找到对应的Bean,如果该Bean还没有实例化,那么该方法不负责去实例化,只会返回Bean对应的Class对象,表示这个Bean也是结果之一
        3. 根据类型看有没有找到Bean
          1. 如果找到了只有一个,就直接返回该Bean,如果是Class对象,就会调用getBean生成该Bean对象
          2. 如果超过一个
            1. 从多个Bean中选择被@Primary标注了的Bean,如果有多个@Primary会报错
            2. 如果没有@Primary,那么就看Bean上是否通过@Priority定义了优先级,如果定义了就获取优先级最高的Bean
            3. 如果没有优先级,那么就使用descriptor.getDependencyName来确定唯一的Bean
              1. 是否找出唯一的一个Bean
                1. 找出了,也会判断是否是Class对象,如果是,就调用getBean方法去生成Bean对象,然后返回
                2. 如果没找到,判断isReuquired如果是true就报错,否则返回null
        4. 如果没找到,判断isReuquired如果是true就报错,否则返回null

DefaultListableBeanFactory#findAutowireCandidates

Spring中根据类型找beanName底层流程

String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());
public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {Assert.notNull(lbf, "ListableBeanFactory must not be null");// 从本容器中找String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);// 从父容器找并放入resultif (lbf instanceof HierarchicalBeanFactory) {HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {String[] parentResult = beanNamesForTypeIncludingAncestors((ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);result = mergeNamesWithParent(result, parentResult, hbf);}}return result;}
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {// 如果没有冻结,就根据类型去BeanFactory找,如果冻结了,可能就跳过这个if然后去缓存中去拿了if (!isConfigurationFrozen() || type == null || !allowEagerInit) {return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);}// 把当前类型所匹配的beanName缓存起来Map<Class<?>, String[]> cache =(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);String[] resolvedBeanNames = cache.get(type);if (resolvedBeanNames != null) {return resolvedBeanNames;}resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {cache.put(type, resolvedBeanNames);}return resolvedBeanNames;}
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {List<String> result = new ArrayList<>();// Check all bean definitions.// 遍历所有的BeanDefinitionsfor (String beanName : this.beanDefinitionNames) {// Only consider bean as eligible if the bean name is not defined as alias for some other bean.if (!isAlias(beanName)) {try {RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// Only check bean definition if it is complete.// 判断mbd允不允许获取对应类型// 首先mdb不能是抽象的,然后allowEagerInit为true,则直接去推测mdb的类型,并进行匹配// 如果allowEagerInit为false,那就继续判断,如果mdb还没有加载类并且是懒加载的并且不允许提前加载类,那mbd不能用来进行匹配(因为不允许提前加载类,只能在此mdb自己去创建bean对象时// 如果allowEagerInit为false,并且mbd已经加载类了,或者是非懒加载的,或者允许提前加载类,并且不用必须提前初始化才能获取类型,那么就可以去进行匹配了// 这个条件有点复杂,但是如果只考虑大部分流程,则可以忽略这个判断,因为allowEagerInit传进来的基本上都是trueif (!mbd.isAbstract() && (allowEagerInit ||(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&!requiresEagerInitForType(mbd.getFactoryBeanName()))) {boolean isFactoryBean = isFactoryBean(beanName, mbd);BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();boolean matchFound = false;boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());// 当前BeanDefinition不是FactoryBean,就是普通Beanif (!isFactoryBean) {// 在筛选Bean时,如果仅仅只包括单例,但是beanName对应的又不是单例,则忽略if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);}} else {if (includeNonSingletons || isNonLazyDecorated ||(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);}if (!matchFound) {// In case of FactoryBean, try to match FactoryBean instance itself next.beanName = FACTORY_BEAN_PREFIX + beanName;matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);}}if (matchFound) {result.add(beanName);}}} catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {if (allowEagerInit) {throw ex;}// Probably a placeholder: let's ignore it for type matching purposes.LogMessage message = (ex instanceof CannotLoadBeanClassException ?LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));logger.trace(message, ex);// Register exception, in case the bean was accidentally unresolvable.onSuppressedException(ex);} catch (NoSuchBeanDefinitionException ex) {// Bean definition got removed while we were iterating -> ignore.}}}}

Spring之依赖注入底层源码解析(二)

  1. 找出BeanFactory中类型为type的所有bean的名字,注意的是名字而不是bean对象,因为我们可以根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象
  2. 把resolvableDependencies中key为type的对象找出来并且添加到result中
  3. 遍历根据type找出beanName,判断当前beanName对应的Bean是不是能够被自动注入
  4. 先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果是false,表示不能用来进行自动注入,如果是true,就继续进行判断
  5. 判断的当前type是不是泛型,如果是泛型,会把容器中所有的beanName找出来,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么就继续判断
  6. 如果当前DependencyDescriptor上存在@Qualifier注解,那么就要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等就匹配
  7. 经过上述验证后,当前beanName才能成为一个可注入的,添加到result中

依赖注入流程

Spring之依赖注入底层源码解析(二)

依赖注入中泛型注入的实现

首先在Java反射中,有一个Type接口,表示类型,具体分类为:

  1. raw types:也就是普通Class
  2. parameterized types:对应ParameterizedType接口,泛型类型
  3. array types:对应GenericArrayType,泛型数组
  4. type variables:对应TypeVariable接口,表示类型变量,也就是所定义的泛型,比如T、K
  5. primitive types:基本类型,int、boolean

我们可以看下下面的打印结果:

public class TypeTest<T> { private int i; private Integer it; private int[] iarray; private List list; private List<String> slist; private List<T> tlist; private T t; private T[] tarray; public static void main(String[] args) throws NoSuchFieldException {test(TypeTest.class.getDeclaredField("i"));System.out.println("=======");test(TypeTest.class.getDeclaredField("it"));System.out.println("=======");test(TypeTest.class.getDeclaredField("iarray"));System.out.println("=======");test(TypeTest.class.getDeclaredField("list"));System.out.println("=======");test(TypeTest.class.getDeclaredField("slist"));System.out.println("=======");test(TypeTest.class.getDeclaredField("tlist"));System.out.println("=======");test(TypeTest.class.getDeclaredField("t"));System.out.println("=======");test(TypeTest.class.getDeclaredField("tarray"));} public static void test(Field field) {  if (field.getType().isPrimitive()) {System.out.println(field.getName() + "是基本数据类型");} else {System.out.println(field.getName() + "不是基本数据类型");}  if (field.getGenericType() instanceof ParameterizedType) {System.out.println(field.getName() + "是泛型类型");} else {System.out.println(field.getName() + "不是泛型类型");}  if (field.getType().isArray()) {System.out.println(field.getName() + "是普通数组");} else {System.out.println(field.getName() + "不是普通数组");}  if (field.getGenericType() instanceof GenericArrayType) {System.out.println(field.getName() + "是泛型数组");} else {System.out.println(field.getName() + "不是泛型数组");}  if (field.getGenericType() instanceof TypeVariable) {System.out.println(field.getName() + "是泛型变量");} else {System.out.println(field.getName() + "不是泛型变量");}}}
i是基本数据类型i不是泛型类型i不是普通数组i不是泛型数组i不是泛型变量=======it不是基本数据类型it不是泛型类型it不是普通数组it不是泛型数组it不是泛型变量=======iarray不是基本数据类型iarray不是泛型类型iarray是普通数组iarray不是泛型数组iarray不是泛型变量=======list不是基本数据类型list不是泛型类型list不是普通数组list不是泛型数组list不是泛型变量=======slist不是基本数据类型slist是泛型类型slist不是普通数组slist不是泛型数组slist不是泛型变量=======tlist不是基本数据类型tlist是泛型类型tlist不是普通数组tlist不是泛型数组tlist不是泛型变量=======t不是基本数据类型t不是泛型类型t不是普通数组t不是泛型数组t是泛型变量=======tarray不是基本数据类型tarray不是泛型类型tarray是普通数组tarray是泛型数组tarray不是泛型变量

在Spring中,如果注入点是泛型,也是会进行处理的

@Componentpublic class UserService extends BaseService<OrderService, StockService> { public void test() {System.out.println(o);}}public class BaseService<O, S> { @Autowired protected O o; @Autowired protected S s;}
  1. Spring扫描时发现UserService是一个Bean

  2. 那就取出注入点,也就是BaseService中的两个属性o和s

  3. 接下来需要按注入点类型进行注入,但是o和s都是泛型,所以Spring需要确定o和s的具体类型

  4. 因为当前正在创建的是UserService的Bean,所以可以通过userService.getClass().getGenericSuperclass().getTypeName()获取到具体的泛型信息

  5. 然后再拿到UserService的父类BaseServuce泛型变量

for (TypeVariable<? extends Class<?>> typeParameter : userService.getClass().getSuperclass().getTypeParameters()) { System._out_.println(typeParameter.getName()); }
  1. 通过上面两段代码,就能知道,o对应的具体就是OrderService,s对应的具体类型就是StockService
  2. 然后再调用oField.getGenericType()就知道当前field使用的是哪个泛型,就能知道具体类型了

Qualifier的使用

我们可以模拟实现负载均衡

@Target({ElementType.TYPE, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Qualifier("random")public @interface Random {}@Target({ElementType.TYPE, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Qualifier("roundRobin")public @interface RoundRobin {}public interface LoadBalance {String select();}@Component@Randompublic class RandomStrategy implements LoadBalance { @Override public String select() {  return null;}}@Component@RoundRobinpublic class RoundRobinStrategy implements LoadBalance { @Override public String select() {  return null;}}

使用

@Componentpublic class UserService  { @Autowired @RoundRobin private LoadBalance loadBalance; public void test() {System.out.println(loadBalance);}}

@Resource

@Resource注解底层工作流程图

Spring之依赖注入底层源码解析(二)

对于@Resouce的具体实现CommonAnnotationBeanPostProcessor#postProcessProperties

@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);try {metadata.inject(bean, beanName, pvs);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);}return pvs;}