1. 前言
Spring的核心之一就是依赖注入,Spring提供了@Autowired
注解来给bean注入依赖。除了注入最基本的bean之外,Spring还做了一些扩展,例如你可以注入Optional
,以此来判断依赖的bean是否存在;你还可以注入Map
来获得所有候选的bean;当然了List
和Set
自然也是支持的。
Spring依赖注入是怎么实现的呢?
2. AutowiredAnnotationBeanPostProcessor
Spring的依赖注入是通过一个叫AutowiredAnnotationBeanPostProcessor
的后置处理器来完成的,先看类图:
它实现了BeanPostProcessor接口,代表它是bean的后置处理器,这一点很好理解,给bean注入所需的依赖,不就是扩展bean嘛。
AutowiredAnnotationBeanPostProcessor何时被注册到容器???
以AnnotationConfigApplicationContext为例,在它的构造函数里会启动Spring容器,启动前会手动向容器内注册几个支撑Spring核心功能的bean,其中就包含AutowiredAnnotationBeanPostProcessor。
构造函数会实例化AnnotatedBeanDefinitionReader
,它的构造函数里会调用AnnotationConfigUtils#registerAnnotationConfigProcessors()
手动注册bean。
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
/**
* @see AutowiredAnnotationBeanPostProcessor
* 完成依赖注入的后置处理器
*/
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
3. 收集注入点
要想完成依赖注入,首先得知道,bean需要注入哪些依赖的bean?
所以在依赖注入前,Spring得先收集注入点。这个收集工作也是由AutowiredAnnotationBeanPostProcessor完成的,方法是AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()
。收集注入点这个步骤是在bean实例化后,初始化前触发的,Spring会调用AbstractAutowireCapableBeanFactory#doCreateBean()
来创建bean,创建bean的第一步就是实例化bean,接着就是对bean进行解析寻找注入点,然后通过AbstractAutowireCapableBeanFactory#populateBean()
填充bean的属性,即依赖注入。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 查找注入元数据,注入点
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 写入RootBeanDefinition
metadata.checkConfigMembers(beanDefinition);
}
收集注入点需要解析bean,这个过程是有代价的,所以Spring会将解析过的InjectionMetadata缓存起来,key是beanName,value是InjectionMetadata。
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
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;
}
真正收集注入点的方法是buildAutowiringMetadata()
,首先Spring会递归解析,因为父类属性也是要注入的;然后遍历属性Field,找出需要注入的Field;再遍历方法Method,找出需要注入的Method。注入点会统一包装成InjectedElement
对象,它有两个重要的子类AutowiredFieldElement
和AutowiredMethodElement
,分别代表属性注入和方法注入。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
// 循环递归,因为父类的也要处理
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 属性注入
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
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));
}
});
// 方法注入
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
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 new InjectionMetadata(clazz, elements);
}
beanClass和注入点集合会被封装成InjectionMetadata
对象,代表注入元数据。
4. 依赖注入
依赖注入是通过后置处理器的一个扩展点来实现的,扩展点是InstantiationAwareBeanPostProcessorAdapter#postProcessProperties()
,AutowiredAnnotationBeanPostProcessor实现也很简单,因为前面已经完成了注入点的收集,所以这里仅仅是从缓存里取出InjectionMetadata对象,然后完成注入。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 查找依赖元数据 前面收集扩展点时已经缓存起来了
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;
}
依赖注入的职责交给了InjectionMetadata#inject()
,它会遍历所有的注入点,然后依次完成注入。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
// 优先checkedElements,其次injectedElements
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
/**
* 分为属性注入和Setter方法注入 两种
* @see AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
* @see AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject
*/
element.inject(target, beanName, pvs);
}
}
}
依赖注入的过程由具体的子类去实现,我们以Field注入为例,对应的子类是AutowiredFieldElement。
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
// 查找依赖的bean是有代价的,这里会缓存起来
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
} else {
// 创建依赖描述符
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();
try {
// 容器查找依赖的bean
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {// 加入缓存
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
} else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
// 通过反射设置属性
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
- 依赖注入的第一步,就是从容器里查找出要依赖的bean,这个查找过程比较复杂,且是有代价的,所以Spring会将查找到的bean缓存起来,后续再注入时直接取缓存即可。
- 如果缓存没有,则创建依赖描述符对象
DependencyDescriptor
,调用DefaultListableBeanFactory#resolveDependency()
向容器查找依赖bean。 - 最终,通过反射给Field赋值。
5. 查找依赖bean
查找依赖bean的方法是DefaultListableBeanFactory#resolveDependency()
,除了最简单的依赖注入,Spring还做了一些扩展,例如可以支持注入Optional、ObjectFactory等对象,你甚至可以配合@Lazy
注解一起使用,注入一个延迟加载的bean。对于这种非常规注入,Spring要特殊处理。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
/**
* 方法参数名作为beanName注入,所以需要参数名称解析器
* Spring支持多种获取方法参数名的策略
*/
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
// 支持Optional注入
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 {
// 如果注入的属性加了@Lazy注解 创建代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
if (result == null) {
// 否则容器查找依赖的bean
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
对于常规注入,方法是DefaultListableBeanFactory#doResolveDependency()
:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 尝试快捷注入,前提是已经确定注入的beanName
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 依赖类型
Class<?> type = descriptor.getDependencyType();
// 解析@Value注解 取出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);
value = evaluateBeanDefinitionString(strVal, bd);
}
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()));
}
}
/**
* 如果注入的是 数组、Collection、Map
* 则要返回多个bean
*/
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
/**
* 容器内查找所有的候选bean
* beanName -> bean
*/
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
// 没有候选bean,且是必须的 则抛出异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
// 确定注入的beanName
String autowiredBeanName;
// 确定注入的bean实例
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 存在多个候选bean,决定注入的beanName 3个策略
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
} else {
return null;
}
}
// 根据beanName获取bean
instanceCandidate = matchingBeans.get(autowiredBeanName);
} else {
// 只有单一候选bean的处理
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) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
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);
}
}
- Spring首先会尝试快捷注入,快捷注入的前提条件是已经确定注入的beanName,直接通过容器取出bean即可。
- 其次,Spring判断要注入的是不是一个bean集合,例如List、Map等。如果注入的是集合,Spring会把容器内所有候选bean都取出来,然后构建对应的集合对象返回。
- 接下来就是注入单一bean实例了,Spring先通过
findAutowireCandidates()
找出所有的候选bean构建一个Map,如果没有候选bean且required=true
,则只能抛出异常。 - 如果只有一个候选bean,则直接注入即可。如果存在多个候选bean,则通过
determineAutowireCandidate()
来决定最终注入的beanName。
6. 候选bean筛选
如果容器内有多个候选bean,Spring该注入哪一个呢???
筛选最终注入的beanName方法是DefaultListableBeanFactory#determineAutowireCandidate()
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 查找@Primary bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// OrderComparator#getPriority() 优先级
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// 兜底方案 根据属性名/方法名 匹配beanName
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
- Spring优先查找加了
@Primary
注解的bean,作为首选注入。 - 其次通过
OrderComparator#getPriority()
获取bean的优先级。 - 如果还是没有高优先级的bean,Spring还有一个兜底方案,尝试通过属性名/方法名去匹配beanName。