目录
一、概述
spring为了简化配置xml代码,在2.5版本后逐步加入了注解的方法,减少了xml文件的代码量。到3.0版本之后,甚至省略了xml文件,使用JavaConfig配置类以及annotation注解来进行依赖注入。
@Autowired就是spring提供的注解之一,是用来替换之前写在xml文件里autowired属性的。它默认是按照类型进行匹配,自动注入一个符合要求的bean,通过set方法注入,且set方法可以省略。@Autowired可以修饰在属性以及方法上。
语法形式:
@Autowired(required="true")
将required的属性设置为true是指所修饰的类型是必须注入,设置此属性后
·如果没有找到一个与之匹配的bean对象,则会抛出NoSuchBeanDefinitionException异常
·如果成功匹配到一个对象,则完成自动注入
·如果按类型匹配到多个可注入的bean对象,则会按照名称继续匹配,若按名称也未匹配成功,则会抛出NoUniqueBeanDefinitionException异常
二、实现原理
存在位置:
由图可以看出,@Autowired位于org.springframework.beans.factory.annotation包下
@Autowired的实现,就是调用了AutowiredAnnotationBeanPostProcessor类中的方法:
1、核心方法postProcessProperties()
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 将需要自动装配的属性和方法参数封装在对象中
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 利用反射给该对象赋值
metadata.inject(bean, beanName, pvs);
return pvs;
} catch (BeanCreationException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
}
}
2、findAutowiringMetadata()方法返回metadata对象
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
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);
}
metadata = this.buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
3、inject()方法完成注入
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (!this.checkPropertySkipping(pvs)) {
Method method = (Method)this.member;
Object[] arguments;
if (this.cached) {
try {
arguments = this.resolveCachedArguments(beanName);
} catch (NoSuchBeanDefinitionException var8) {
arguments = this.resolveMethodArguments(method, bean, beanName);
}
} else {
arguments = this.resolveMethodArguments(method, bean, beanName);
}
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
} catch (InvocationTargetException var7) {
throw var7.getTargetException();
}
}
}
}