概述
对于一个bean
中成员属性方式的依赖和成员方法参数方式的依赖,会在这个bean
创建过程中属性填充阶段对这些依赖进行依赖注入。具体地讲,这两种形式的依赖如下例子所示 :
@Component
public class BeanA {}
@Component
public class BeanB {}
@Component
public class DemoBean {
// 成员属性依赖
@Autowired;
private BeanA a;
// 成员方法参数依赖
private BeanB b;
@Autowired
public void setB(BeanB b){
this.b=b;
}
// 成员属性依赖
@Value("#{city}")
private String c;
}
而bean
属性填充的大致位置位于 :
AbstractBeanFactory#getBean
=> AbstractBeanFactory#doGetBean
=> DefaultSingletonBeanRegistry#getSingleton
=> AbstractAutowireCapableBeanFactory#createBean
=> AbstractAutowireCapableBeanFactory#doCreateBean
=> AbstractAutowireCapableBeanFactory#populateBean
=> AutowiredAnnotationBeanPostProcessor#postProcessProperties
源代码分析
1.AutowiredAnnotationBeanPostProcessor#postProcessProperties
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 这里获取目标bean每个需要注入的依赖,metadata会包含一组元素,每个元素对应一个目标bean :
// 1. @Autowired/@Value 注解的属性 或者
// 2. @Autowired/@Value 注解的方法参数
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 执行依赖注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed",
ex);
}
return pvs;
}
2.InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs)
throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍历目标bean每个需要注入的成员属性依赖或者成员方法参数依赖,执行相应的依赖注入
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
3.InjectedElement#inject
3.1 AutowiredMethodElement#inject
成员方法参数依赖的注入 :
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)
throws Throwable {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam,
this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
// 依赖解析使用 beanFactory#resolveDependency
Object arg = beanFactory.resolveDependency(currDesc, beanName,
autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName,
new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
Object[] cachedMethodArguments = new Object[paramTypes.length];
System.arraycopy(descriptors, 0, cachedMethodArguments, 0,
arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == paramTypes.length) {
Iterator<String> it = autowiredBeans.iterator();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
3.2 AutowiredFieldElement#inject
成员属性依赖注入 :
@Override
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 {
// 依赖解析使用 beanFactory#resolveDependency
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);
}
}
从上面的代码可见,最终成员属性/成员方法参数依赖的解析最终都是通过BeanFactory#resolveDependency
。关于BeanFactory#resolveDependency
如何工作,可以参考"Spring 依赖解决过程分析"。