目录
五、AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()源码
六、AutowiredAnnotationBeanPostProcessor#postProcessProperties()源码
@Autowired注解大家再熟悉不过了,在项目中使用 @Autowired注解的比例非常高,可以说基本用过 Spring 的同学都接触过这个注解,因此,我们有必要详细了解一下其工作原理。
@Autowired注解的作用是帮我们注入我们需要的对象,Spring会自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
在分析这个注解的实现原理之前,我们不妨先来回顾一下@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 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这个注解在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后置处理器主要负责对添加了@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 elements = new ArrayList<>();
Class> targetClass = clazz;
do {
// 存放找到的元数据信息
final List 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()方法的处理流程:
在本例中,目标类是com.wsh.autowired.UserServiceImpl,此时目标类中有一个字段userDao,如下图:
然后通过findAutowiredAnnotation(field)方法查找此属性是否被@Autowired注解修饰,很显然,我们的userDao使用了@Autowired注解修饰,所以能够获取到注解的属性信息:
(2)、通过反射获取目标类中所有的方法,跟前面处理字段的过程类似;
(3)、将每个字段或者方法解析到的元信息保存到List
(4)、将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata,然后返回;
buildAutowiringMetadata()方法执行完成后,会将解析得到的自动注入相关信息保存到缓存injectionMetadataCache中,如下图:
总结:AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法的作用其实是,找到目标bean对象中的属性或者方法是否使用了@Autowired注解修饰,如果有@Autowired注解修饰,将会解析得到注解相关信息,将需要依赖注入的属性信息封装到InjectionMetadata类中,InjectionMetadata类中包含了哪些需要注入的元素及元素要注入到哪个目标类中。并将其存入到缓存injectionMetadataCache中,方便后面使用。说简单点,AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()方法其实就是找到那些需要自动装配的元素。
前面分析到,在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()方法的处理流程:
首先会调用findAutowiringMetadata()方法,在前面已经分析过了,findAutowiringMetadata()方法将目标类对应的@Autowired注解元信息都已经解析好了,存入到缓存injectionMetadataCache中,所以 这里我们直接从缓存中获取即可。
这里主要分析metadata.inject(bean, beanName, pvs)方法。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection checkedElements = this.checkedElements;
Collection 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 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后置处理器中实现的,主要分为两个步骤:
通过一张图来回顾一下@Autowired自动注入的流程:
下面我们总结一下Spring Bean的自动装配过程:
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦