網站首頁 編程語言 正文
一、概念:@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)方法是關鍵
原文鏈接:https://blog.csdn.net/l1050188952/article/details/125959694
相關推薦
- 2023-01-07 Python中層次聚類的詳細講解_python
- 2022-08-27 Python+matplotlib繪制多子圖的方法詳解_python
- 2022-01-27 laravel的服務注入新增service層,多方式
- 2022-08-20 pip安裝路徑修改的詳細方法步驟_python
- 2022-07-01 Oracle中的索引講解_oracle
- 2023-12-07 ant 循環多條通知提醒框堆疊問題
- 2022-11-12 Redis主從復制操作和配置詳情_Redis
- 2022-01-06 Spring Aware接口詳解
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支