版本: Spring-beans-5.2.5.RELEASE
假定环境中存在两个User对象,分别是user、superUser,其中superUser标注了primary属性,根据这个前提条件,来看看Spring如何查找要依赖注入的对象
@Configuration
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理) + 延迟
@Lazy
private User lazyUser;
@Autowired // 依赖查找(处理)
private User user;
@Autowired // 集合类型依赖注入
private Map<String, User> users; // user superUser
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
Spring框架的依赖查找工作由DefaultListableBeanFactory
类负责,它实现了AutowireCapableBeanFactory
接口,该接口中定义了如下解析依赖属性的方法
public interface AutowireCapableBeanFactory extends BeanFactory {
// ...
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
*/
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName)
throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
*/
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
throws BeansException;
}
从上面的resolveDependency`接口定义中可以了解都需要一个
DependencyDescriptor``对象,这个类描述了一个依赖属性的相关信息,如下:
public class DependencyDescriptor extends InjectionPoint implements Serializable {
// 属性定义在哪个类中,本例中值为AnnotationDependencyInjectionResolutionDemo
private final Class<?> declaringClass;
@Nullable
private String methodName; // 通过方法注入可用的方法名称
@Nullable
private Class<?>[] parameterTypes;
private int parameterIndex;
@Nullable
private String fieldName; // 属性名称
private final boolean required; // 对应@Autowired注解的required属性
private final boolean eager; // 对应@Lazy注解,是否懒加载,懒加载此项为false
private int nestingLevel = 1; // 嵌套层数
@Nullable
private Class<?> containingClass; // 类似declaringClass属性
@Nullable
private volatile ResolvableType resolvableType; // 属性的类型描述
// ...
}
再来看看DefaultListableBeanFactory
的实现,针对普通类型的Bean,Spring会判断当前依赖属性是单一类型还是多类型,针对单一类型,如果查找到多个候选bean,则判断是否有首选Bean可以返回,否则抛出异常,而针对多类型的属性依赖,直接遍历所有符合的Bean返回
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// ...
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 首先,可以看到Spring先判断依赖注入的属性是否为
// Optional、ObjectFactory、javaxInjectProviderClass 类型之一
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
} 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, requestingBeanName);
} else {
// 由于本例没有上面的任何注入类型,会走这个分支,
// 同时,第一个LazyUser属性由于标注了@Lazy注解,那么会直接生成一个CGLIB代理对象返回
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// user和users属性则进入当前方法
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 省略和本例无关代码...
// users属性将会通过这个方法直接返回查找到的对象
// 顾名思义,这是一个解析多个bean集合属性的方法
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// user属性将会通过这个方法获得两个候选bean信息,即user、superUser
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 通过这个方法推断如果有多个候选bean可以注入单一类型属性,则尝试推断
// 是否有哪个属性标注了@Primary之类的主要bean信息,通过这里得到superUser
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();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// 最终通过这个方法从beanFactory中获取目标bean返回
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
// 省略...
return result;
} finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
// 处理多元素属性的注入查找
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
final Class<?> type = descriptor.getDependencyType();
if (descriptor instanceof StreamDependencyDescriptor) {
// ...
} else if (type.isArray()) {
// ...
} else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
// ...
} else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (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;
}
}
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// ... 省略
// 注意本方法返回的是Map<String,Object>,
// 当解析多元素注入属性的时候,value为具体的bean,通过这个方法获取具体的bean
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
// ... 省略
}
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDescriptor) {
// 通过这个方法向beanFactory获取目标bean
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
if (!(beanInstance instanceof NullBean)) {
candidates.put(candidateName, beanInstance);
}
}
// ...
}
}
参考图