1. 用法
之前有篇文章介绍了Spring循环依赖的流程 解决循环依赖的手段很简单。可以用@Autowired作用于字段或者方法上
方法一:setter注入
@Component
public class A {
private B b;
@Autowired
public void setB(B b) {
this.b = b;
}
}
@Component
public class B {
private A a;
@Autowired
public void setA(A a) {
this.a = a;
}
}
方法二:@Autowired直接作用于字段上
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
2. 原理分析
首先看Autowired源码
/*
* @author Juergen Hoeller
* @author Mark Fisher
* @author Sam Brannen
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
从注释中可以看出,实现类是在AutowiredAnnotationBeanPostProcessor中实现的。并且required属性默认为true,说明运行的时候,被@Autowired注解标记的bean必须存在,否则会报错。大家可以试试将上面示例代码中的类AService去掉@Service注解,在启动准会报错,原因见后面源码分析。
AutowiredAnnotationBeanPostProcessor
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
···
}
因为之前我debug过Spring中bean的初始化流程. Spring bean的初始化
所以,这里的AutowiredAnnotationBeanPostProcessor中方法执行前后顺序是
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
1. 执行 postProcessMergedBeanDefinition方法
将标注@Autowired注解的字段或者方法存入InjectionMetadata对象中
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
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);
}
// 构造InjectionMetadata对象
metadata = buildAutowiringMetadata(clazz);
// 将构造好的InjectionMetadata对象放入injectionMetadataCache缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 判断该类是否携带@Autowired或者@Value(在类型,方法或字段上)
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<>();
// 遍历该类所有字段是否带有@Autowired或者@Value
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// 字段不能用static修饰,否则注入不了
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 获取@Autowired中的属性required,默认为true
boolean required = determineRequiredStatus(ann);
// 创建一个AutowiredFieldElement封装字段信息以及required值
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 遍历该类所有方法是否带有@Autowired或者@Value
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> 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);
// 创建一个AutowiredMethodElement封装字段信息以及required值
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
//迭代,继续遍历父类
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
// 封装成InjectionMetadata对象
return InjectionMetadata.forElements(elements, clazz);
}
2. 执行 postProcessPropertyValues 方法
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//从缓存中injectionMetadataCache取出InjectionMetadata对象
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;
}
然后进入到 org.springframework.beans.factory.annotation.InjectionMetadata#inject方法
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) {
if (logger.isDebugEnabled()) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
// 这里因为AutowiredAnnotationBeanPostProcessor重写了InjectedElement
element.inject(target, beanName, pvs);
}
}
}
在AutowiredAnnotationBeanPostProcessor中重写了InjectedElement,分别有AutowiredMethodElement与AutowiredFieldElement。
因为我们例子中是在字段上标注的注解,所以我们这里以AutowiredFieldElement举例:
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
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 {
// 获取被@Autowired标注的bean ‘Aservice’
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);
}
}
一路追踪.DefaultListableBeanFactory#resolveDependency代码 DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
···
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 如果matchingBeans找不到对应的bean则返回null
if (matchingBeans.isEmpty()) {
// required默认为true,那么这里会抛出NoSuchBeanDefinitionException异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
···下面实例化bean代码省略
// 不为null就根据matchingBeans获取对应的bean实例
}
private void raiseNoMatchingBeanFound(
Class<?> type, ResolvableType resolvableType, DependencyDescriptor descriptor) throws BeansException {
checkBeanNotOfRequiredType(type, descriptor);
throw new NoSuchBeanDefinitionException(resolvableType,
"expected at least 1 bean which qualifies as autowire candidate. " +
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
}
DefaultListableBeanFactory#findAutowireCandidates 终于发现了关键代码
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
...
如果默认的@Autowired,里面required为true,那么这里如果将类'Aservice'上的注解@Service去掉,那么在上面这行代码中找不到对应的beanName,就会返回null。
找到的话,就正常获取bean实例返回,最后通过反射赋值。
3. 总结
其实@Resource注解源码跟@Autowired实现类似,实现类是在CommonAnnotationBeanPostProcessor中,大家可以尝试自己看一下。
还有这篇文章中,AutowiredAnnotationBeanPostProcessor该类不仅仅处理了@Autowired注解,其实还有个@Value注解,单独开了一篇@Value的实现原理。
最后,@Autowired注解作用在字段上,其实就是通过AutowiredFiledElement中的field.set(bean, valu)注入,作用在方法上,就是通过AutowiredMethodElement中的method.invoke(bean, arguments)。