当前位置:网站首页>注解@Autowired如何自动装配
注解@Autowired如何自动装配
2022-07-26 04:58:00 【l1050188952】
一、概念:@Autowired是spring框架2.5之后出现,用来简化在bean当中需要定义属性实现自动装配的注解,夜市最常见注解之一。
二、作用位置:可以修饰在方法,参数和注解等属性上(以下是源码)
//可以修饰的位置包括, 构造方法, 普通方法, 参数,
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER,
/* 字段,*/ /* 注解 */
ElementType.FIELD, ElementType.ANNOTATION_TYPE})
//保留策略是在运行时
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
//声明了依赖属性 默认是true
boolean required() default true;
}从我们看到的Autowired源码中是没有任何关于自动装配的代码的,完成自动装配的代码是在AutowiredAnnotationBeanPostProcessor类中。

<一>找到需要装配的元素并保存(解析Autowired)
1.进源码可以看见,AutowiredAnnotationBeanPostProcessor实现了
MergedBeanDefinitionPostProcessor接口,重写postProcessMergedBeanDefinition()方法,实现的注入类型的预解析。
//源码中的预加载方法
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName) {
InjectionMetadata metadata
= this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
metadata.checkConfigMembers(beanDefinition);
}2.主要逻辑是在findAutowiringMetadata()方法。这个方法主要是找到需要自动装配的元素,该方法会去调用buildAutowiringMetadata()方法构建元数据信息。
// findAutowiringMetadata源码
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//缓存Bean的名称
String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
//判断缓存是否存在
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized(this.injectionMetadataCache) {
metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//目标Bean的元数据信息
metadata = this.buildAutowiringMetadata(clazz);
//存入缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}3.核心逻辑在buildAutowiringMetadata()方法中
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
LinkedList<InjectedElement> elements = new LinkedList();
Class targetClass = clazz;
do {
LinkedList<InjectedElement> currElements = new LinkedList();
//通过反射获取目标类中所有的字段,并遍历每一个字段,然后通过findAutowiredAnnotation() 方法判断字段是否使用@Autowired和@Value修饰,
// 如果字段被@Autowired和@Value修饰,则返回注解的相关属性信息
ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
AnnotationAttributes ann = this.findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 获取到@Autowired注解的required()的值
boolean required = this.determineRequiredStatus(ann);
// 将该字段封成AutowiredFieldElement对象
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
}
});
//反射获取目标Bean的所有方法
ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
AnnotationAttributes ann = this.findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0 && this.logger.isWarnEnabled()) {
this.logger.warn("Autowired annotation should only be used on methods with parameters: " + method);
}
boolean required = this.determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 将该字段封成AutowiredMethodElement对象
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
// 循环处理父类需要自动装配的元素
while(targetClass != null && targetClass != Object.class);
// 将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata,然后合并到Bean定义中
return new InjectionMetadata(clazz, elements);
}buildAutowiringMetadata()方法的步骤:
1》通过反射获取目标类中所有的字段并进行遍历,然后通过findAutowiredAnnotation()方法判断字段是否使用@Autowired和@Value修饰,如果字段被@Autowired和@Value修饰,则返回注解的所有属性信息。
2》通过反射获取目标类中所有的方法;
3》解析到字段和方法的元信息保存到List<InjectionMetadata.InjectedElement> elements集合中,字段对应的是AutowiredFieldElement类型,方法对应的则是AutowiredMethodElement类型。
4》将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata类,返回
buildAutowiringMetadata()方法执行完成后,会将解析得到的自动注入相关信息保存到缓存injectionMetadataCache
4.postProcessMergedBeanDefinition()方法将需要注入的属性信息通过checkConfigMembers()
封装在了InjectionMetadata类中,包含了装配和内装配类的所有信息。
public class InjectionMetadata {
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
private final Class<?> targetClass;
private final Collection<InjectionMetadata.InjectedElement> injectedElements;
@Nullable
private volatile Set<InjectionMetadata.InjectedElement> checkedElements;
public InjectionMetadata(Class<?> targetClass, Collection<InjectionMetadata.InjectedElement> elements) {
this.targetClass = targetClass;
this.injectedElements = elements;
}
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<InjectionMetadata.InjectedElement> checkedElements = new LinkedHashSet(this.injectedElements.size());
Iterator var3 = this.injectedElements.iterator();
while(var3.hasNext()) {
InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var3.next();
Member member = element.getMember();
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
beanDefinition.registerExternallyManagedConfigMember(member);
checkedElements.add(element);
if (logger.isDebugEnabled()) {
logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
this.checkedElements = checkedElements;
}<二>自动注入属性
AutowiredAnnotationBeanPostProcessor间接实现了InstantiationAwareBeanPostProcessor接口,所以会执行到postProcessProperties()方法实现自动注入属性。
*postProcessProperties()方法的处理流程:
1.调用findAutowiringMetadata()方法,尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取;
2.循环InjectionMetadata的injectedElements属性,全部调用InjectionMetadata.InjectedElement.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);
}
}
}
总结:以上分了两部分去说,一是解析@Autowired方法,到反射获取目标类的属性和方法,到存入injectionMetadataCache中,关键是buildAutowiringMetadata()方法。二是自动注入属性,还是反射的方式,取injectionMetadataCache中元信息,inject(bean, beanName, pvs)方法是关键
边栏推荐
- Briefly describe the application fields of WMS warehouse management system
- ES6模块化+CommonJS
- [semantic segmentation] 2018-deeplabv3+ ECCV
- 9 best project set management tools
- AQS唤醒线程的时候为什么从后向前遍历,我懂了
- 计算离散点的曲率(matlab)
- 【语义分割】2018-DeeplabV3+ ECCV
- 3、 @requestmapping annotation
- NFT的几种发行方式你都了解过吗?不同的发行方式有什么优缺点?
- [300 + selected interview questions from big companies continued to share] big data operation and maintenance sharp knife interview question column (VIII)
猜你喜欢

data warehouse

Icml2022 | imitation learning by evaluating the professional knowledge of the presenter

推荐系统-机器学习

UE4 controls the rotation of objects by pressing keys

What is the difference between asynchronous and synchronous transmission signals (electronic hardware)

AQS唤醒线程的时候为什么从后向前遍历,我懂了

Molecular skeleton transition tool -delinker introduction
![[mathematical modeling] analytic hierarchy process (AHP)](/img/20/8ebd951a0e0c46d1967c6c8b078a4a.png)
[mathematical modeling] analytic hierarchy process (AHP)

C language - pointer one touch ※

Codeforces Round #807 (Div. 2)
随机推荐
Briefly describe the application fields of WMS warehouse management system
What are the demand management software for small and medium-sized enterprises
2022 a.static query on tree (tree section)
The importance of supporting horizontal expansion of time series database
5、 Domain objects share data
What is the real HTAP? (1) Background article
What are the characteristics of the grammar of Russian documents in the translation of scientific papers
[uoj 429] runs (inclusive) + a little record about Lyndon tree and its application
UE4 keyboard control switch light
奥特学园ROS笔记--6
Axi protocol (4): signals on the Axi channel
汉字风格迁移篇---通过生成对抗网络学习一对多程式化汉字的转换和生成
What is the difference between asynchronous and synchronous transmission signals (electronic hardware)
1、 Basic introduction
ES6模块化+CommonJS
嵌入式实操----基于RT1170 FreeRTOS实现CPU使用率统计(二十四)
Array sort 3
【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(八)
Stm32fsmc extended SRAM
[mathematical modeling] basic knowledge of MATLAB