- BeanFactory#resolveDependency
- Spring中根据类型找Bean的底层流程
- DefaultListableBeanFactory#findAutowireCandidates
- Spring中根据类型找beanName底层流程
- 依赖注入流程
- @Qualifier使用
- @Resource注解底层工作流程
@Nullable Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable SetautowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
该方法表示,传入一个依赖描述DependencyDescriptor,该方法会根据依赖描述从BeanFactory中找出对应的唯一的一个Bean对象
我们可以分析一下BeanFactory的实现类DefaultListableBeanFactory#resolveDependency方法的具体实现
Spring中根据类型找Bean的底层流程public Object resolveDependency(DependencyDescriptor descriptor, @Nullable St @Nullable SetautowiredBeanNames, @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; } }
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable SetautowiredBeanNames, @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 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 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 SetautowiredBeanNames, @Nullable TypeConverter typeConverter) { Class> type = descriptor.getDependencyType(); if (descriptor instanceof StreamDependencyDescriptor) { // 找到type所匹配的所有bean Map matchingBeans = findAutowireCandidates(beanName, type, descriptor if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } // 构造成一个stream Stream
-
调用DefaultListableBeanFactory#resolveDependency
-
判断依赖的类型
-
如果是Optional,调用doResolveDependency
-
如果是ObjectFactory或ObjectProvider,在调用ObjectFactory#getObject方法时调用doResolveDependency
-
如果依赖上有@Lazy注解.那么就会生成一个代理对象然后返回,那么在调用代理对象中的方法时调用doResolveDependency
-
-
-
对于上面的doResolveDependency执行逻辑如下
- 判断是否存在@Value注解
- 如果存在,获取并且解析descriptor上的@Value注解,进行解析后并且返回
- 判断descriptor的类型
- 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的方法不用进一步做筛选了
- 调用findAutowireCandidate,findAutowireCandidate该方法会返回一个Map,表示会根据类型去找Bean,Map的key为beanName,Map的value为对象,对于value可能是Bean对象也可能是某Bean的class对象,因为该方法只负责根据类型找到对应的Bean,如果该Bean还没有实例化,那么该方法不负责去实例化,只会返回Bean对应的Class对象,表示这个Bean也是结果之一
- 根据类型看有没有找到Bean
- 如果找到了只有一个,就直接返回该Bean,如果是Class对象,就会调用getBean生成该Bean对象
- 如果超过一个
- 从多个Bean中选择被@Primary标注了的Bean,如果有多个@Primary会报错
- 如果没有@Primary,那么就看Bean上是否通过@Priority定义了优先级,如果定义了就获取优先级最高的Bean
- 如果没有优先级,那么就使用descriptor.getDependencyName来确定唯一的Bean
- 是否找出唯一的一个Bean
- 找出了,也会判断是否是Class对象,如果是,就调用getBean方法去生成Bean对象,然后返回
- 如果没找到,判断isReuquired如果是true就报错,否则返回null
- 是否找出唯一的一个Bean
- 如果没找到,判断isReuquired如果是true就报错,否则返回null
- 判断是否存在@Value注解
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);
// 从父容器找并放入result
if (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, 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 result = new ArrayList<>();
// Check all bean definitions.
// 遍历所有的BeanDefinitions
for (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传进来的基本上都是true
if (!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,就是普通Bean
if (!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.
}
}
}
}
- 找出BeanFactory中类型为type的所有bean的名字,注意的是名字而不是bean对象,因为我们可以根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象
- 把resolvableDependencies中key为type的对象找出来并且添加到result中
- 遍历根据type找出beanName,判断当前beanName对应的Bean是不是能够被自动注入
- 先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果是false,表示不能用来进行自动注入,如果是true,就继续进行判断
- 判断的当前type是不是泛型,如果是泛型,会把容器中所有的beanName找出来,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么就继续判断
- 如果当前DependencyDescriptor上存在@Qualifier注解,那么就要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等就匹配
- 经过上述验证后,当前beanName才能成为一个可注入的,添加到result中
首先在Java反射中,有一个Type接口,表示类型,具体分类为:
- raw types:也就是普通Class
- parameterized types:对应ParameterizedType接口,泛型类型
- array types:对应GenericArrayType,泛型数组
- type variables:对应TypeVariable接口,表示类型变量,也就是所定义的泛型,比如T、K
- primitive types:基本类型,int、boolean
我们可以看下下面的打印结果:
public class TypeTest{ private int i; private Integer it; private int[] iarray; private List list; private List slist; private List 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中,如果注入点是泛型,也是会进行处理的
@Component public class UserService extends BaseService{ public void test() { System.out.println(o); } } public class BaseService { @Autowired protected O o; @Autowired protected S s; }
-
Spring扫描时发现UserService是一个Bean
-
那就取出注入点,也就是BaseService中的两个属性o和s
-
接下来需要按注入点类型进行注入,但是o和s都是泛型,所以Spring需要确定o和s的具体类型
-
因为当前正在创建的是UserService的Bean,所以可以通过userService.getClass().getGenericSuperclass().getTypeName()获取到具体的泛型信息
-
然后再拿到UserService的父类BaseServuce泛型变量
for (TypeVariable extends Class>> typeParameter : userService.getClass().getSuperclass().getTypeParameters()) { System._out_.println(typeParameter.getName());
}
- 通过上面两段代码,就能知道,o对应的具体就是OrderService,s对应的具体类型就是StockService
- 然后再调用oField.getGenericType()就知道当前field使用的是哪个泛型,就能知道具体类型了
我们可以模拟实现负载均衡
@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
@Random
public class RandomStrategy implements LoadBalance {
@Override
public String select() {
return null;
}
}
@Component
@RoundRobin
public class RoundRobinStrategy implements LoadBalance {
@Override
public String select() {
return null;
}
}
使用
@Component
public class UserService {
@Autowired
@RoundRobin
private LoadBalance loadBalance;
public void test() {
System.out.println(loadBalance);
}
}
@Resource
@Resource注解底层工作流程图
对于@Resouce的具体实现CommonAnnotationBeanPostProcessor#postProcessProperties
@Override
public 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;
}



