Spring中@Autowired注解的工作原理

目录

一、概述

二、@Autowired注解的用法

三、@Autowired自动装配原理

四、源码调试环境

五、AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()源码

六、AutowiredAnnotationBeanPostProcessor#postProcessProperties()源码

七、总结


一、概述

@Autowired注解大家再熟悉不过了,在项目中使用 @Autowired注解的比例非常高,可以说基本用过 Spring 的同学都接触过这个注解,因此,我们有必要详细了解一下其工作原理。

@Autowired注解的作用是帮我们注入我们需要的对象,Spring会自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。

在分析这个注解的实现原理之前,我们不妨先来回顾一下@Autowired注解的用法。

二、@Autowired注解的用法

先定义几个接口:

@Repository
public class UserDao {

	public void insert() {
		// 执行数据库操作
	}

}

public interface UserService {

	void insert();

}

@Autowired注解的主要使用方式有下面四种:

  • (一)、@Autowired注解应用于构造函数
@Service
public class UserServiceImpl implements UserService {

	private final UserDao userDao;

	@Autowired
	public UserServiceImpl(UserDao userDao) {
		this.userDao = userDao;
	}

	@Override
	public void insert() {
		userDao.insert();
	}

}
  • (二)、@Autowired注释应用于setter方法
@Service
public class UserServiceImpl implements UserService {

	private UserDao userDao;

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Override
	public void insert() {
		userDao.insert();
	}

}

  • (三)、@Autowired应用于字段
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDao userDao;

	@Override
	public void insert() {
		userDao.insert();
	}

}
  • (四)、@Autowired应用于类型数组/集合对象的字段或方法
public interface ICalculateStrategy {
	void calculate();
}

@Component
public class StategyA implements ICalculateStrategy {
	@Override
	public void calculate() {

	}
}

@Component
public class StategyB implements ICalculateStrategy {
	@Override
	public void calculate() {

	}
}

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private ICalculateStrategy[] calculateStrategies;

	@Autowired
	private List<ICalculateStrategy> calculateStrategyList;

	@Override
	public void insert() {
		//[com.wsh.autowired.StategyA@490d6c15, com.wsh.autowired.StategyB@7d4793a8]
		System.out.println(Arrays.toString(calculateStrategies));
		//[com.wsh.autowired.StategyA@490d6c15, com.wsh.autowired.StategyB@7d4793a8]
		System.out.println(calculateStrategyList);
	}

}

@Configuration
@ComponentScan("com.wsh.autowired")
public class AppConfig {

}

public class Client {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) annotationConfigApplicationContext.getBean("userServiceImpl");
		userService.insert();
	}
}

三、@Autowired自动装配原理

首先看一下@Autowired这个注解在Spring中的定义:

// 可作用于: 构造方法、普通方法、参数、字段、注解上
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
// 保留策略是运行时
@Retention(RetentionPolicy.RUNTIME)
// @Documented: 表明是否在java doc中添加Annotation
@Documented
public @interface Autowired {

	/**
	 * 声明这个依赖是否必须,默认为true
	 */
	boolean required() default true;

}

我们可以看到,@Autowired注解可以应用在构造方法,普通方法,参数,字段,以及注解这五种类型的地方,它的保留策略是在运行时。在Spring中,@Autowired注解位于org.springframework.beans.factory.annotation包下面,我们发现在这个包下面还有一个关键的类:AutowiredAnnotationBeanPostProcessor。

看名字盲猜AutowiredAnnotationBeanPostProcessor可能与@Autowired自动注入功能有关,确实,Spring对@Autowired注解的实现逻辑就在AutowiredAnnotationBeanPostProcessor实现的。

先看一下AutowiredAnnotationBeanPostProcessor类的继承关系图:

可以看到,AutowiredAnnotationBeanPostProcessor间接实现了InstantiationAwareBeanPostProcessor和

MergedBeanDefinitionPostProcessor两个BeanPostProcessor后置处理器接口,通过之前的文章,大家对BeanPostProcessor应该不陌生了,Spring很多功能都是利用BeanPostProcessor后置处理器来实现的。

  • MergedBeanDefinitionPostProcessor类:合并Bean的定义信息
// 合并Bean的定义信息的后处理方法,该方法是在Bean的实例化之后设置值之前调用。
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法的调用时机是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors方法,而applyMergedBeanDefinitionPostProcessors()方法是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean通过反射创建bean的实例之后调用的。

  • InstantiationAwareBeanPostProcessor类:在 Bean 实例化前后和Bean设置属性值时执行的后置处理器
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    throws BeansException {

    return null;
}

在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean()给bean的属性赋值方法中,会执行InstantiationAwareBeanPostProcessor的postProcessProperties()方法回调,如下图:

postProcessProperties()方法的作用: 允许对填充前的属性进行处理(如对属性的验证)

回顾一下Spring的创建流程:doCreateBean()通过反射创建bean的实例 -> applyMergedBeanDefinitionPostProcessors()执行MergedBeanDefinitionPostProcessor后置处理器增强方法postProcessMergedBeanDefinition() -> populateBean()属性填充 -> 执行InstantiationAwareBeanPostProcessor的postProcessProperties()方法回调 -> 初始化bean。

可以看到,在实例化bean之后,就会调用AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法,然后在属性填充的时候,会调用AutowiredAnnotationBeanPostProcessor#postProcessProperties方法,我们按照这个先后顺序进行分析。

所以,我们将重点关注在AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法以及AutowiredAnnotationBeanPostProcessor#postProcessProperties方法即可,下面挨个进行分析。

四、源码调试环境

下面以一个示例来跟踪@Autowired的整体执行流程。代码比较简单,这里就不过多说明,如下所示:

@Repository
public class UserDao {

	public void insert() {
		// 执行数据库操作
	}

}

public interface UserService {

	void insert();

}

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDao userDao;

	@Override
	public void insert() {
	}

}

@Configuration
@ComponentScan("com.wsh.autowired")
public class AppConfig {

}

public class Client {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) annotationConfigApplicationContext.getBean("userServiceImpl");
		userService.insert();
	}
}

Spring 是如何实现自动装配的呢? 我们慢慢往下看(注意:主要以 @Autowired 为例来讲解)

五、AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()源码

AutowiredAnnotationBeanPostProcessor后置处理器主要负责对添加了@Autowired和@Value注解的元素实现自动装配。所以找到需要自动装配的元素,其实就是对@Autowired和@Value注解的解析,找出需要自动装配的元素是在MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()方法中实现的,而AutowiredAnnotationBeanPostProcessor间接实现了MergedBeanDefinitionPostProcessor,所以我们从AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法开始分析。

我们以Debug方式启动Client,当我们执行new AnnotationConfigApplicationContext(AppConfig.class)时,会执行Spring IOC容器的初始化,熟悉IOC的小伙伴都知道,在刷新容器方法refresh()中有一个非常关键的步骤:finishBeanFactoryInitialization(beanFactory),那就是实例化所有剩下的非懒加载的单例Bean。

本例中我们主要分析userServiceImpl这个bean的实例化过程。

执行getBean("userServiceImpl") -> doCreateBean("userServiceImpl"),在doCreateBean()方法中,有一个方法:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);它会执行MergedBeanDefinitionPostProcessor后置处理器增强方法postProcessMergedBeanDefinition(),允许修改 MergedBeanDefinition。

由于AutowiredAnnotationBeanPostProcessor间接实现了MergedBeanDefinitionPostProcessor,所以会执行到

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法,如下图。

接着我们看下AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法的源码:

// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

postProcessMergedBeanDefinition()方法主要逻辑是在findAutowiringMetadata()方法。这个方法主要是找到需要自动装配的元素,该方法会去调用buildAutowiringMetadata()方法构建元数据信息。

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    // 缓存key, 在本例中就是bean的名称:userServiceImpl
    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);
                }
                // 获取目标类对应的自动注入相关的元数据信息
                metadata = buildAutowiringMetadata(clazz);
                // 存入缓存
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

核心逻辑在buildAutowiringMetadata()方法,源码如下:

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        // 存放找到的元数据信息
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        // 通过反射获取目标类中所有的字段,并遍历每一个字段,然后通过findAutowiredAnnotation()方法判断字段是否使用@Autowired和@Value修饰,
        // 如果字段被@Autowired和@Value修饰,则返回注解的相关属性信息
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // findAutowiredAnnotation(): 判断字段是否使用@Autowired和@Value修饰,并返回相关属性
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            if (ann != null) {
                // 校验@Autowired和@Value修饰注解是否应用在static方法上
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                // 获取到@Autowired注解的required()的值
                boolean required = determineRequiredStatus(ann);
                // 将该字段封成AutowiredFieldElement对象
                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;
                }
                // 判断方法的参数个数是否为0
                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对象
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    // 循环处理父类需要自动装配的元素
    while (targetClass != null && targetClass != Object.class);
    // 将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata,然后合并到Bean定义中
    // 包含所有带有@Autowired注解修饰的一个InjectionMetadata集合. 由两部分组成: 一是我们处理的目标类,二就是上述方法获取到的所以elements集合。
    return new InjectionMetadata(clazz, elements);
}

buildAutowiringMetadata()方法的处理流程:

  • (1)、通过反射获取目标类中所有的字段,并遍历每一个字段,然后通过findAutowiredAnnotation()方法判断字段是否使用@Autowired和@Value修饰,如果字段被@Autowired和@Value修饰,则返回注解的相关属性信息;

在本例中,目标类是com.wsh.autowired.UserServiceImpl,此时目标类中有一个字段userDao,如下图:

然后通过findAutowiredAnnotation(field)方法查找此属性是否被@Autowired注解修饰,很显然,我们的userDao使用了@Autowired注解修饰,所以能够获取到注解的属性信息:

  • (2)、通过反射获取目标类中所有的方法,跟前面处理字段的过程类似;
  • (3)、将每个字段或者方法解析到的元信息保存到List<InjectionMetadata.InjectedElement> elements集合中,字段对应的是AutowiredFieldElement类型,方法对应的则是AutowiredMethodElement类型,等待下一步的自动装配;
  • (4)、将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata,然后返回;

buildAutowiringMetadata()方法执行完成后,会将解析得到的自动注入相关信息保存到缓存injectionMetadataCache中,如下图:

总结:AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法的作用其实是,找到目标bean对象中的属性或者方法是否使用了@Autowired注解修饰,如果有@Autowired注解修饰,将会解析得到注解相关信息,将需要依赖注入的属性信息封装到InjectionMetadata类中,InjectionMetadata类中包含了哪些需要注入的元素及元素要注入到哪个目标类中。并将其存入到缓存injectionMetadataCache中,方便后面使用。说简单点,AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法其实就是找到那些需要自动装配的元素。

六、AutowiredAnnotationBeanPostProcessor#postProcessProperties()源码

前面分析到,在doCreateBean()方法中,会执行applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)方法,然后会调用到AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法,此方法主要完成解析@Autowired和@Value注解相关自动注入信息,并将解析之后的结果存入缓存中,接下来就需要自动注入属性了。

在doCreateBean()方法执行后,接着就是执行populateBean("userServiceImpl")完成userServiceImpl这个bean的属性填充。

如上图,在populateBean("userServiceImpl")方法中,会执行InstantiationAwareBeanPostProcessor的postProcessProperties()方法回调。

AutowiredAnnotationBeanPostProcessor间接实现了InstantiationAwareBeanPostProcessor接口,所以会执行到

AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法,如下图:

AutowiredAnnotationBeanPostProcessor后置处理器注入属性值是在postProcessPropertyValues()方法中实现的。一起看下AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法的实现:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 首先尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 循环InjectionMetadata的injectedElements属性,挨个调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值
        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;
}

postProcessProperties()方法的处理流程:

  1. 调用findAutowiringMetadata()方法,尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取;
  2. 循环InjectionMetadata的injectedElements属性,挨个调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值;

首先会调用findAutowiringMetadata()方法,在前面已经分析过了,findAutowiringMetadata()方法将目标类对应的@Autowired注解元信息都已经解析好了,存入到缓存injectionMetadataCache中,所以 这里我们直接从缓存中获取即可。

这里主要分析metadata.inject(bean, beanName, pvs)方法。

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()) {
        // 循环elementsToIterate, 挨个调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值;
        for (InjectedElement element : elementsToIterate) {
            if (logger.isTraceEnabled()) {
                logger.trace("Processing injected element of bean '" + beanName + "': " + element);
            }
            element.inject(target, beanName, pvs);
        }
    }
}

通过AutowiredAnnotationBeanPostProcessor的源码,我们可以发现,在AutowiredAnnotationBeanPostProcessor类中,定义了AutowiredFieldElement以及AutowiredMethodElement:

private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
    
}

private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
    
}

所以,当执行element.inject(target, beanName, pvs)方法的时候,也是调用到AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject()方法。

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 {
            // 解析依赖对象,实际上是从bean工厂中获取目标对象所依赖的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);
        // 通过反射方式设置字段的值
        // 在本例中,就是注入userServiceImpl类中的userDao属性
        // bean - userServiceImpl
        // value - userDao对象
        // field - UserServiceImpl中的userDao属性
        field.set(bean, value);
    }
}

从源码中我们看到,核心逻辑就是通过beanFactory.resolveDependency()方法从bean工厂中获取依赖的对象。跟踪一下resolveDependency()方法可以发现,底层会调用到org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate()方法,而resolveCandidate()方法内部其实是通过beanFactory.getBean("userDao")从bean容器中获取到userDao这个bean对象。如下图:

依赖的userDao对象获取成功后,将会通过反射方式field.set(bean, value)设置userServiceImpl这个bean对象中的userDao属性的值。如下图:

到这里,@Autowired就完成了依赖对象的注入工作,接着将会执行populateBean()属性填充后续的一系列处理流程。

七、总结

通过前面的分析,我们已经知道了@Autowired完成自动装配主要是在AutowiredAnnotationBeanPostProcessor后置处理器中实现的,主要分为两个步骤:

  • 找出需要自动装配的元素:具体实现在AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法;
  • 注入属性:具体实现在AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法;

通过一张图来回顾一下@Autowired自动注入的流程:

下面我们总结一下Spring Bean的自动装配过程:

  1. 根据Class目标类类型,通过反射获取其所有的Field和Method信息,然后判断字段或者方法上面是否添加了@Autowired和@Value注解,以此来判断是否需要自动装配;
  2. 如果标注有@Autowired和@Value注解,表示需要自动装配,则会将需要自动装配的元素,封装成AutowiredFieldElement(针对字段)或AutowiredMethodElement(针对方法)对象;
  3. 调用AutowiredFieldElement或AutowiredMethodElement的inject方法,通过反射,调用容器的getBean()方法找到需要注入的Bean对象,然后注入到目标Bean中;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值