目錄
1. 說明
Spring使用依賴注入,完成對IOC容器中各個組件的依賴注入,@Autowired就是Spring提供對其他組件注入的註解,@Autowired的定義如下:
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
定義組件的依賴是否是必輸的
*/
boolean required() default true;
}
2. 注入規則
1)、默認優先按照類型去容器中找對應的組件:applicationContext.getBean(UserDao.class),找到就賦值;
2)、如果找到多個相同類型的組件,再將屬性的名稱作爲組件的id去容器中查找 applicationContext.getBean("userDao")
3)、@Qualifier("userDao"):使用@Qualifier指定需要裝配的組件的id,而不是使用屬性名;
4)、自動裝配默認一定要將屬性賦值好,沒有就會報錯;可以使用@Autowired(required=false);
5)、@Primary:讓Spring進行自動裝配的時候,默認使用首選的bean,也可以繼續使用@Qualifier指定需要裝配的bean的名字;
3. 註解分析
調用鏈如下:
依賴注入攔截方法:org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement.inject(Object, String, PropertyValues)
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 找出需要注入的組件
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
//依賴注入
field.set(bean, value);
}
}