Spring IoC @Autowired 註解詳解
阿新 • • 發佈:2020-07-08
# 前言
本系列全部基於 `Spring 5.2.2.BUILD-SNAPSHOT` 版本。因為 Spring 整個體系太過於龐大,所以只會進行關鍵部分的原始碼解析。
我們平時使用 Spring 時,想要 **依賴注入** 時使用最多的是 `@Autowired` 註解了,本文主要講解 Spring 是如何處理該註解並實現 **依賴注入** 的功能。
# 正文
首先我們看一個測試用例:
`User` 實體類:
```java
public class User {
private Long id;
private String name;
// 省略 get 和 set 方法
}
```
測試類:
```java
public class AnnotationDependencyInjectTest {
/**
* @Autowired 欄位注入
*/
@Autowired
private User user;
private City city;
/**
* @Autowired 方法注入
*/
@Autowired
public void initCity(City city) {
this.city = city;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AnnotationDependencyInjectTest.class);
context.refresh();
AnnotationDependencyInjectTest bean = context.getBean(AnnotationDependencyInjectTest.class);
// @Autowired 欄位注入
System.out.println(bean.user);
// @Autowired 方法注入
System.out.println(bean.city);
UserHolder userHolder = context.getBean(UserHolder.class);
// @Autowired 構造器注入
System.out.println(userHolder.getUser());
context.close();
}
@Bean
public User user() {
User user = new User();
user.setId(1L);
user.setName("leisurexi");
return user;
}
@Bean
public City city() {
City city = new City();
city.setId(1L);
city.setName("北京");
return city;
}
/**
* @Autowired 建構函式注入
*/
static class UserHolder {
private User user;
@Autowired
public UserHolder(User user) {
this.user = user;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
}
```
上面分別展示了 `@Autowired` 註解的欄位注入和方法注入,下面我們開始分析 Spring 是如何實現的。
首先使 `@Autowired` 註解生效的一個關鍵類是 `AutowiredAnnotationBeanPostProcessor`,該類實現了 `InstantiationAwareBeanPostProcessorAdapter` 抽象類;該抽象類就是一個介面卡的作用提供了介面方法的預設實現,`InstantiationAwareBeanPostProcessorAdapter` 又實現了 `SmartInstantiationAwareBeanPostProcessor` 介面,同時實現該介面的 `determineCandidateConstructors()` 方法可以指定 `bean` 的候選建構函式;然後 `SmartInstantiationAwareBeanPostProcessor` 介面又繼承了 `InstantiationAwareBeanPostProcessor` 介面,該介面提供了 `bean` 例項化前後的生命週期回撥以及屬性賦值前的後置處理方法,`@Autowired` 註解的屬性注入就是通過重寫該介面的 `postProcessProperties()` 實現的。這兩個介面都在 [Spring IoC bean 的建立](https://www.cnblogs.com/leisurexi/p/13196998.html) 一文中有介紹過。下面我們看一下 `AutowiredAnnotationBeanProcessor` 的繼承關係圖:
![](http://ww1.sinaimg.cn/large/006Vpl27gy1gfjts4v6uqj30x70dvt9g.jpg)
關於 `AutowiredAnnotationBeanPostProcessor` 這個後置處理器是怎麼加入到 `beanFactory` 中的,我們在 [Spring IoC component-scan 節點詳解](https://www.cnblogs.com/leisurexi/p/13088395.html) 一文中介紹過主要是通過 `AnnotationConfigUtils#registerAnnotationConfigProcessors()` 實現的。
```java
public static Set registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
// 省略其他程式碼...
// 註冊用於處理@Autowired、@Value、@Inject註解的後置處理器
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 省略其他程式碼...
}
```
## 屬性和方法注入
`AutowiredAnnotationBeanPostProcessor` 中跟屬性注入有關的方法有兩個:`postProcessMergedBeanDefinition` 和 `postProcessPropertyValues`。
前者是 `MergedBeanDefinitionPostProcessor` 介面中的方法,定義如下:
```java
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
* 對指定bean的BeanDefinition合併後的處理方法回撥
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName);
// 省略其他程式碼...
}
```
後者是 `InstantiationAwareBeanPostProcessor` 介面中的方法,定義如下:
```java
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Bean 例項化後屬性賦值前呼叫,PropertyValues 是已經封裝好的設定的屬性值,返回 {@code null} 繼續
* 使用現有屬性,否則會替換 PropertyValues。
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
// 省略其他程式碼...
}
```
關於這兩個方法的呼叫時機,可以檢視[Spring IoC bean 的建立](https://www.cnblogs.com/leisurexi/p/13196998.html)和[Spring IoC 屬性賦值階段](https://www.cnblogs.com/leisurexi/p/13234465.html)。
### bean 合併後處理
#### AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
首先執行的是 `postProcessMergedBeanDefinition()` 方法。
```java
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
// 尋找需要注入的欄位或方法,並封裝成 InjectionMetadata,見下文詳解
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 檢查元資料中的註解資訊
metadata.checkConfigMembers(beanDefinition);
}
```
`InjectionMetadata` 就是注入的元資訊描述,主要欄位如下:
```java
public class InjectionMetadata {
// 需要依賴注入的目標類
private final Class> targetClass;
// 注入元素的集合
private final Collection injectedElements;
// 忽略其它程式碼
}
```
`InjectedElement` 就是注入的元素,主要欄位如下:
```java
public abstract static class InjectedElement {
// 注入的屬性或方法
protected final Member member;
// 需要注入的是否是欄位
protected final boolean isField;
}
```
### 查詢需要注入的欄位或方法
#### AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
```java
private InjectionMetadata findAutowiringMetadata(String beanName, Class> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 首先從快取中獲取
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 判斷是否需要重新整理,即metadata為null或者metadata中儲存的targetClass和當前clazz不等
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
// 這裡相當於是一個double check,防止多執行緒出現的併發問題
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;
}
```
### 建立需要注入的元資訊
#### AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
```java
private InjectionMetadata buildAutowiringMetadata(final Class> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
// 判斷當前類或其欄位或其方法是否標註了autowiredAnnotationTypes中的註解,沒有的話直接返回空的
List elements = new ArrayList<>();
Class> targetClass = clazz;
do {
final List currElements = new ArrayList<>();
// 遍歷targetClass中的欄位
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 獲取field上的@Autowired註解資訊
MergedAnnotation> 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;
}
// 獲取@Autowired註解中的required屬性
boolean required = determineRequiredStatus(ann);
// 將裝成AutowiredFieldElement新增進currElements
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 遍歷targetClass中的方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 找到橋接方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
// 判斷方法的可見性,如果不可見則直接返回
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 獲取method上的@Autowired註解資訊
MergedAnnotation> 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);
}
}
// 獲取@Autowired註解中的required屬性
boolean required = determineRequiredStatus(ann);
// 將方法和目標型別封裝成屬性描述符
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 封裝成AutowiredMethodElement新增進currElements
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
// 將currElements整個新增進elements
elements.addAll(0, currElements);
// 獲取targetClass的父類,進行下一次迴圈
targetClass = targetClass.getSuperclass();
}
// 當targetClass為空或者targetClass等於Object.class時會退出迴圈
while (targetClass != null && targetClass != Object.class);
// 將elements和clazz封裝成InjectionMetadata返回
return InjectionMetadata.forElements(elements, clazz);
}
```
上面程式碼中的 `findAutowiredAnnotation()` 就是在遍歷 `autowiredAnnotationTypes` 屬性,看欄位或者方法上的註解是否存在於 `autowiredAnnotationTypes` 中,或者其派生註解,找到第一個就返回,不會再繼續遍歷了。
```java
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
private final Set> autowiredAnnotationTypes = new LinkedHashSet<>(4);
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.
}
}
}
```
從 `AutowiredAnnotationBeanPostProcessor` 類的建構函式中,我們可以發現 `autowiredAnnotationTypes` 預設添加了 `@Autowired`、`@Value` 以及 `@Inject` (在 JSR-330 的jar包存在於當前環境時)。
至此,使用 `@Autowired` 修飾的欄位和方法已經封裝成 `InjectionMetadata` 並放在 `injectionMetadataCache` 快取中,便於後續使用。
### bean 屬性的後置處理
#### AutowireAnnotationBeanPostProcessor#postProcessProperties
`postProcessMergedBeanDefinition()` 呼叫後 `bean` 就會進行例項化接著呼叫 `postProcessProperties()` 。
```java
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 獲取快取中的 InjectionMetadata
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;
}
// InjectMetadata.java
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 獲取檢查後的元素
Collection checkedElements = this.checkedElements;
// 如果checkedElements不為空就使用checkedElements,否則使用injectedElements
Collection elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍歷elementsToIterate
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// AutowiredFieldElement、AutowiredMethodElement這兩個類繼InjectionMetadata.InjectedElement
// 各自重寫了inject方法
element.inject(target, beanName, pvs);
}
}
}
```
### 欄位注入
#### AutowiredFieldElement#inject
```java
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 強轉成Field型別
Field field = (Field) this.member;
Object value;
if (this.cached) {
// 如果快取過,直接使用快取的值,一般第一次注入都是false
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
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 加鎖
synchronized (this) {
// 如果沒有被快取
if (!this.cached) {
// 找到了需要的bean || 該欄位是必要的
if (value != null || this.required) {
// 將依賴描述符賦值給cachedFieldValue
this.cachedFieldValue = desc;
// 註冊bean的依賴關係,用於檢測是否迴圈依賴
registerDependentBeans(beanName, autowiredBeanNames);
// 如果符合條件的bean只有一個
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
// beanFactory含有名為autowiredBeanName的bean && 型別是匹配的
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 將該屬性解析到的bean的資訊封裝成ShortcutDependencyDescriptor
// 之後可以通過呼叫resolveShortcut()來間接調beanFactory.getBean()快速獲取bean
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
// 快取標識設定為true
this.cached = true;
}
}
}
// 如果找到了符合的bean,設定欄位可訪問,利用反射設定值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
```
上面程式碼中的 `beanFactory.resolveDependency()` 在 [Spring IoC bean 的建立](https://www.cnblogs.com/leisurexi/p/13196998.html) 一文中有介紹過,這裡不再贅述;同樣 `registerDependentBeans()` 最終會呼叫 `DefaultSingletonBeanRegistry.registerDependentBean()` ,該方法在 [Spring IoC bean 的建立](https://www.cnblogs.com/leisurexi/p/13196998.html) 一文中有介紹過,這裡也不再贅述。
### 方法注入
#### AutowiredMethodElement#inject
```java
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 檢查是否需要跳過
if (checkPropertySkipping(pvs)) {
return;
}
// 強轉成Method型別
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
// 如果快取過,直接呼叫beanFactory.resolveDependency()返回符合的bean
arguments = resolveCachedArguments(beanName);
}
else {
// 獲取引數數量
int argumentCount = method.getParameterCount();
arguments = new Object[argumentCount];
// 建立依賴描述符陣列
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
// 記錄用於自動注入bean的名稱集合
Set autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
// 獲取型別轉換器
TypeConverter typeConverter = beanFactory.getTypeConverter();
// 遍歷引數
for (int i = 0; i < arguments.length; i++) {
// 將方法和引數的下標構建成MethodParameter,這裡面主要記錄了引數的下標和型別
MethodParameter methodParam = new MethodParameter(method, i);
// 將MethodParameter構建成DependencyDescriptor
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
// 進行依賴解決,找到符合條件的bean
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
// 這裡跟欄位注入差不多,就是註冊bean的依賴關係,並且快取每個引數的ShortcutDependencyDescriptor
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator it = autowiredBeans.iterator();
Class>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
// 找到了符合條件的bean
if (arguments != null) {
try {
// 設定方法可訪問,利用反射進行方法呼叫,傳入引數
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
```
## 構造器注入
構造器注入就是通過呼叫 `determineCandidateConstructors()` 來返回合適的構造器。
```java
public Constructor>[] determineCandidateConstructors(Class> beanClass, final String beanName) throws BeanCreationException {
// Quick check on the concurrent map first, with minimal locking.
// 首先從快取中獲取
Constructor>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
// 快取為空
if (candidateConstructors == null) {
// Fully synchronized resolution now...
// 這裡相當於double check
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor>[] rawCandidates;
try {
// 獲取beanClass的所有建構函式
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
// 存放標註了@Autowired註解的構造器
List> candidates = new ArrayList<>(rawCandidates.length);
// 存放標註了@Autowired註解,並且required為true的構造器
Constructor> requiredConstructor = null;
Constructor> defaultConstructor = null;
for (Constructor> candidate : rawCandidates) {
// 獲取構造器上的@Autowired註解資訊
MergedAnnotation> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
// 如果沒有從候選者找到註解,則嘗試解析beanClass的原始類(針對CGLIB代理)
Class> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
if (ann != null) {
// 如果requiredConstructor不為空,代表有多個標註了@Autowired且required為true的構造器,此時Spring不知道選擇哪個丟擲異常
if (requiredConstructor != null) {
throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " + requiredConstructor);
}
// 獲取@Autowired註解的reuired屬性的值
boolean required = determineRequiredStatus(ann);
if (required) {
// 如果當前候選者是@Autowired(required = true),則之前不能存在其他使用@Autowire註解的建構函式,否則拋異常
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " + candidate);
}
// required為true將當前構造器賦值給requiredConstructor
requiredConstructor = candidate;
}
// 將當前構造器加入進候選構造器中
candidates.add(candidate);
}
// 沒有標註了@Autowired註解且引數長度為0,賦值為預設構造器
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
// 有標註了@Autowired註解的構造器
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
// 沒有標註了@Autowired且required為true的構造器
if (requiredConstructor == null) {
// 預設構造器不為空
if (defaultConstructor != null) {
// 將預設構造器加入進候選構造器中
candidates.add(defaultConstructor);
}
}
// 將候選者賦值給candidateConstructors
candidateConstructors = candidates.toArray(new Constructor>[0]);
}
// 只有1個構造器 && 引數長度大於0(非預設構造器),只能用它當做候選者了
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor>[] {rawCandidates[0]};
}
// 只有1個構造器 && 引數長度大於0,只能用它當做候選者了
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor>[] {primaryConstructor};
}
// 返回一個空的Constructor
else {
candidateConstructors = new Constructor>[0];
}
// 快取候選的構造器
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
// 如果候選構造器長度大於0,直接返回,否則返回null
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
```
關於 `SmartInstantiationAwareBeanPostProcessor` 介面的呼叫時機,在 [Spring IoC bean 的建立](https://www.cnblogs.com/leisurexi/p/13196998.html) 一文中有介紹過,這裡就不再贅述了。
# 總結
本文主要介紹了 Spring 對 `@Autowired` 註解的主要處理過程,結合前面的 [Spring IoC bean 的載入](https://www.cnblogs.com/leisurexi/p/13194515.html) 和 [Spring IoC bean 的建立](https://www.cnblogs.com/leisurexi/p/13196998.html) 以及 [Spring IoC 屬性賦值階段](https://www.cnblogs.com/leisurexi/p/13234465.html) 一起看才能更好的理解。
> 最後,我模仿 Spring 寫了一個精簡版,程式碼會持續更新。地址:[https://github.com/leisurexi/tiny-spring](https://github.com/leisurexi/tiny-spr