@Autowired註解使用及原理
使用說明
陣列或集合的注入
Spring容器中所有了型別匹配的bean都被注入進來,並且如果bean有@Order註解或者實現Order介面,按照Order的先後順序注入;
Map的注入
- key的型別必須為String,注入後值為bean的名稱;
- value型別即為想要注入的bean類,所有型別匹配的bean會被注入進來;
In case of a {@link java.util.Collection} or {@link java.util.Map} dependency type, the container autowires all beans matching the declared value type. For such purposes, the map keys must be declared as type String which will be resolved to the corresponding bean names. Such a container-provided collection will be ordered, taking into account {@link org.springframework.core.Ordered}/{@link org.springframework.core.annotation.Order} values of the target components, otherwise following their registration order in the container. Alternatively, a single matching target bean may also be a generally typed {@code Collection} or {@code Map} itself, getting injected as such.
父類屬性的注入
應用場景:父類或抽象類中存在公共依賴的bean時;
public abstract class AbstractTest { @Autowired private TestService1 testService1; public abstract void test(); public TestService1 getTestService1() { return testService1; } public void setTestService1(TestService1 testService1) { this.testService1 = testService1; } }
@Component public class TestImpl extends AbstractTest{ @Autowired private TestService2 testService2; public TestImpl(){ System.out.println("TestImpl()"); } @Override public void test() { testService2.t2(); TestService1 testService1 = this.getTestService1(); testService1.t1(); } }
required屬性
required屬性值可以為true( 預設值)和false。如果為true的話,沒有匹配的類則丟擲異常;如果為false,則表示不是強制必須能夠找到相應的類,無論是否注入成功,都不會拋錯。
工作原理
註解解析器:AutowiredAnnotationBeanPostProcessor
- Spring容器啟動時,AutowiredAnnotationBeanPostProcessor被註冊到容器;
- 掃描程式碼,如果帶有@Autowired註解,則將依賴注入資訊封裝到InjectionMetadata中(見掃描過程);
- 建立bean時(例項化物件和初始化),會呼叫各種BeanPostProcessor對bean初始化,AutowiredAnnotationBeanPostProcessor負責將相關的依賴注入進來;
@Autowired掃描過程
- 掃描當前類中標註@Autowired的屬性和方法;
- 再查詢父類中注@Autowired的屬性和方法,依次遍歷;
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
do {
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("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.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("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);
參考: