使用Autowired装配属性时,当容器在扫描中扫描到@Autowired时,就会在IOC容器中自动的查找到需要的Bean对象(先按照类型进行装配)。当查询结果是一个的时候,就会直接进行装配。当查询的结果有多个的时候,@Autowired会根据名称进行查找(自动切换按照名称(bean对象的Id)进行装配)。
使用方法
1.通过set方法进行类型自动装配,并且set方法可以省略。语法:@Autowired(required="true“)如果IOC容器中没有一个匹配的bean对象。并且制定required属性为true就会抛出NoSuchBeanDefinitionException异常,如果required属性为“false”,就不会抛出这种异常
package com.alibaba.controller;
import com.alibaba.service.IService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.sound.midi.SoundbankResource;
@Controller
public class ControllerImp implements IController {
@Autowired
private IService service;
@Override
public void add() {
System.out.println("——->这是controller层的add()方法");
service.add();
}
}
package com.alibaba.service;
import com.alibaba.dao.IDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ServiceImp implements IService{
@Autowired
private IDao dao;
@Override
public void add() {
System.out.println("——->这是service层的add()方法");
dao.add();
}
}
package com.alibaba.dao;
import org.springframework.stereotype.Repository;
@Repository
public class DaoImp implements IDao{
@Override
public void add() {
System.out.println("——-->这是dao层的add()方法");
}
}
如上,设置了三层。在测试类中从Ioc容器中获取ControllerImp对象,调用它的add()方法,会发现三层串联着调用,说明@Autowired已经自动注入了bean对象。
当IOC容器中有多个对象时,@Autowired会自动切换成按照名称进行装配。
package com.alibaba.dao;
import org.springframework.stereotype.Repository;
@Repository(value = "dao2")
public class DaoImp2 implements IDao {
@Override
public void add() {
System.out.println("--->这是dao2的add方法");
}
}
package com.alibaba.service;
import com.alibaba.dao.IDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ServiceImp implements IService{
@Autowired
private IDao dao2;
@Override
public void add() {
System.out.println("——->这是service层的add()方法");
dao2.add();
}
}
如果容器中有多个对象可以与之匹配,这时会自动切换按照名称装配,但是按照名称却没有与之匹配的对象。这时程序会抛出NoUniqueBeanDefinitionException异常
@Autowired注解的实现过程就是调用了AutowiredAnnotationBeanPostProcessor类中的方法。
核心方法postProcessProperties:
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//1.获取当前类中标注了@Autowired的成员变量和方法的参数封装在metadata对象里
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//2.利用反射赋值
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);
}
}
1.调用findAutowiringMetadata方法查询
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//获取当前bean的名称
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);
}
//调用此方法解析当前类,获得所有标注@AutoWired的字段 并存入metada中
metadata = this.buildAutowiringMetadata(clazz);
//存入缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
//返回得到@AutoWired的字段的metadata
return metadata;
}
2.执行inject方法完成属性注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//metadata中的数据放在集合中
Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
Collection<Injectio
nMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
if (!((Collection)elementsToIterate).isEmpty()) {
Iterator var6 = ((Collection)elementsToIterate).iterator();
//遍历集合拿到标注了@AutoWired的成员变量和方法
while(var6.hasNext()) {
InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
//遍历调用内部类的方法完成属性赋值
element.inject(target, beanName, pvs);
}
}
}
inject方法:
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
//判断是方法还是成员变量
if (this.isField) {
//得到bean的Field对象
Field field = (Field)this.member;
//底层做了判断然后停止修饰符检查
ReflectionUtils.makeAccessible(field);
//利用反射给成员变量赋值
field.set(target, this.getResourceToInject(target, requestingBeanName));
} else {
if (this.checkPropertySkipping(pvs)) {
return;
}
try {
//得到bean的方法对象
Method method = (Method)this.member;
//停止修饰符检查
ReflectionUtils.makeAccessible(method);
//利用invoke给targe赋值,值为此方法的返回值
method.invoke(target, this.getResourceToInject(target, requestingBeanName));
} catch (InvocationTargetException var5) {
throw var5.getTargetException();
}
}
}