【Spring】自动装配
程序员文章站
2024-02-15 11:56:34
...
本文分析基于Spring 5.2.x源码
自动装配模式
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire
Spring官网列出了四种自动装配模式,分别是
- no
- byName
- byType
- constructor
在使用xml对Spring配置时,可以通过标签的default-autowire对所有在xml中配置的Bean设置自动装配模式,也可以通过标签的autowire属性对单个Bean进行设置。
然而值得注意的是在通过标签属性设置自动装配模式时会有5个可选值。其实default就是no,因为设置default时Bean的autowireMode属性也是0。
如果不使用xml配置,也可以通过实现BeanFactoryPostProcessor接口实现对单个Bean设置自动装配模式。
@Autowired
无论是上述哪种方式,对象必须提供其属性字段的setter方法,否则无法完成自动装配。
个人理解@Autowired也是一种装配模式,而且通过源码可以发现这种装配方式并不依赖属性的setter方法,它是通过反射对属性赋值完成自动装配的。下面通过源码证明:
protected void inject(Object bean, @Nullable String beanName, @Nullable 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<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
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) &&
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);
}
}
通过实例化Bean的方法调用链可以看到调用了AutowiredAnnotationBeanPostProcessor的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法,该方法为加了@Autowired注解的属性赋值。