ITPub博客

首页 > 数据库 > 数据库开发技术 > 老铁,天天码的Autowired注解你知道怎么实现的吗?

老铁,天天码的Autowired注解你知道怎么实现的吗?

原创 数据库开发技术 作者:服务端技术栈 时间:2023-01-11 08:20:00 0 删除 编辑

好久没有更文了,祝大家2023新年快乐,2023年还是要继续更新文章,记录自己学习的过程,同时分享给有需要的朋友,一起学习。


前言


Autowired注解是Spring提供自动装配功能的注解,通过这个注解,Spring能够在bean的依赖注入时注入相应的bean属性。

作为Java开发者,每天都可能用到Autowire注解,理解这个注解的实现流程是很有必要的,本文将介绍@Autowired的工作原理。

先说结论:

Spring是通过一个

AutowiredAnnotationBeanPostProcessor

后置处理器(后置处理器是Spring框架提供的扩展点,第三方可以通过该接口扩展或集成Spring)来实现@Autowired的功能,这个后置处理器即实现了MergedBeanDefinitionPostProcessor的

postProcessMergedBeanDefinition

方法功能,又实现了

InstantiationAwareBeanPostProcessorAdapter

后置处理器的postProcessProperties方法和postProcessPropertyValues。


原理分析

下面我们先分析这两个后置处理的提供的功能。

一、Autowired注解元信息解析过程:MergedBeanDefinitionPostProcessor

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/*** 提供修改beandefinition的回调函数* @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors*/void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
/*** 重置回调,可用于清理资源* @see DefaultListableBeanFactory#resetBeanDefinition*/default void resetBeanDefinition(String beanName) {
}}

既然MergedBeanDefinitionPostProcessor有修改beandefinition的能力,那么看下AutowiredAnnotationBeanPostProcessor是怎么运用这个能力的。


public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//需要处理的注解类型private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
//这里是注解和注解目标对应的对象类信息缓存,避免多次读取private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
/*** 这里可以看出默认会处理@Autowired,@Value,@Inject注解*/@SuppressWarnings("unchecked")public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);this.autowiredAnnotationTypes.add(Value.class);this.autowiredAnnotationTypes.add((Class<? extends Annotation>)ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
}
/*** 实现MergedBeanDefinitionPostProcessor接口方法,提供修改beandefinition的能力*/@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//查找当前bean类型里所有加了autowiredAnnotationTypes注解的属性元信息InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
//将这些元信息和beandefinition绑定metadata.checkConfigMembers(beanDefinition);
}
@Overridepublic void resetBeanDefinition(String beanName) {
this.lookupMethodsChecked.remove(beanName);this.injectionMetadataCache.remove(beanName);}
}

findAutowiringMetadata方法就是查找bean类型里符合autowiredAnnotationTypes的元信息

//根据class信息查找属性或方法的自动装配元信息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);}metadata = buildAutowiringMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata;
}
//根据class信息查找自动装配注解元信息和目标属性和方法信息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);}

上面的步骤通过解析得到了符合自动装配注解bean的属性对象和方法对象,并和bean的definition进行绑定。这就是AutowiredAnnotationBeanPostProcessor利用MergedBeanDefinitionPostProcessor扩展点实现的功能。

二、Autowired注解注入对象流程:InstantiationAwareBeanPostProcessorAdapter

上一步这里只是解析到了需要自动装配的属性,还没有注入相应对象。那么注入对象的过程由AutowiredAnnotationBeanPostProcessor实现了InstantiationAwareBeanPostProcessorAdapter的功能。

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//处理属性的功能,即完整自动注入属性@Overridepublic 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;}}

总结

Autowire注解是Java开发中使用最多的注解之一,Spring在实现过程中还是按其他组件实现套路一致共分两个阶段,一阶段是元数据解析,第二阶段是元数据应用,Spring其他组件的学习都可以按这两个阶段来学习,比如

Aop,Transaction等。


老铁!出去面试@Autowire的原理有没有被被问到过?看了今天的文章你还有疑问吗,有没有豁然开朗的感觉?欢迎评论区留言探讨分享您的经历😄

如果您喜欢这个文章,欢迎一键三连,点赞关注转发就是对我最大的支持。

原文作者:服务端技术栈;如有侵权,请联系管理员删除。

下一篇: Spring之IoC容器
请登录后发表评论 登录
全部评论

注册时间:2019-03-08

  • 博文量
    97
  • 访问量
    41429