死磕Spring之IoC篇 - @Autowired 等註解的實現原理
Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
}
```
可以看到會新增 `@Autowired` 和 `@Value` 兩個註解,如果存在 JSR-330 的 `javax.inject.Inject` 註解,也是支援的
#### postProcessMergedBeanDefinition 方法
`postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName)` 方法,找到 `@Autowired` 和 `@Value` 註解標註的欄位(或方法)的元資訊,如下:
```java
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
// 找到這個 Bean 所有需要注入的屬性(@Autowired 或者 @Value 註解)
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
```
直接呼叫 `findAutowiringMetadata(...)` 方法獲取這個 Bean 的**注入元資訊物件**
##### 1. findAutowiringMetadata 方法
```java
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
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;
}
```
首先嚐試從快取中獲取這個 Bean 對應的**注入元資訊物件**,沒有找到的話則呼叫 `buildAutowiringMetadata(final Class> clazz)` 構建一個,然後再放入快取中
##### 2. buildAutowiringMetadata 方法
```java
private InjectionMetadata buildAutowiringMetadata(final Class> clazz) {
List