前言
从前面的章节得知,AbstractAutowireCapableBeanFactory类的createBean方法是创建bean的核心方法,它会调用一个内部方法doCreateBean,该方法的主要流程是这样的:

前面花了多篇文章给介绍,在Spring中bean实例是如何创建的,今天这篇文章,主要给大家介绍一下,bean实例创建完之后,是如何进行依赖注入的。
1 populateBean方法
Spring中的核心功能之一:依赖注入,到底是在哪里完成的?
在doCreateBean方法中,通过createBeanInstance方法创建了bean实例之后,再通过populateBean方法完成的依赖注入。

今天重点看看populateBean方法有哪些功能:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//如果bean为空
if (bw == null) {
//但是有属性,则抛异常
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
//如果没有属性,则直接返回
return;
}
}
//用户可以自定义InstantiationAwareBeanPostProcessor
//可以向bean的成员变量上中注入自定义的信息
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
//获取bean的属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//获取注入类型
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
//如果是按名称注入或者按类型注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//创建一个属性集合对象
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//如果注入类型是按名称注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
//按名称注册
autowireByName(beanName, mbd, bw, newPvs);
}
//如果注入类型是按类型注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//按类型注册
autowireByType(beanName, mbd, bw, newPvs);
}
//赋值属性集合对象
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
//用户可以自定义InstantiationAwareBeanPostProcessor,对属性进行后置处理。
//主要是对@Resource,@Autowired,@Value,@Inject等注解进行注入
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
/**
* 对属性进行过滤,主要过滤三种属性:
* 1. 使用CGLib进行代理的属性
* 2. 需要忽略掉的类型,比如:String
* 3. 需要忽略掉的接口类型,比如:Aware接口
*/
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
//赋值属性集合对象
pvs = pvsToUse;
}
}
//是否需要依赖检查
if (needsDepCheck) {
if (filteredPds == null) {
//对属性进行过滤,逻辑同上
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//检查依赖
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//填充属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
}下面用一张图总结一下populateBean方法的主要流程:

我们重点看看autowireByName、autowireByType、postProcessProperties、filterPropertyDescriptorsForDependencyCheck和applyPropertyValues方法。
2 autowireByName方法
接下来,我们一起看看按名称注册的方法autowireByName,包含了哪些逻辑。
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取非简单属性名称数组
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历属性名称数组
for (String propertyName : propertyNames) {
//判断容器中是否包含该bean属性名称
if (containsBean(propertyName)) {
//根据名称从容器中获取bean实例
Object bean = getBean(propertyName);
//将名称和bean实例保存到集合中
pvs.add(propertyName, bean);
//将bean的依赖关系注册到Spring容器
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}我们可以看到整个autowireByName方法的逻辑是非常简单的。
用一张图总结一下它的主要流程:

接下来,重点看看unsatisfiedNonSimpleProperties方法:
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}该方法主要是遍历所有属性,返回未满足要求的非简单bean属性数组。
属性要满足如下4个条件:
- setter方法不为空。
- 属性被排除在依赖性检查之外,这里主要是判断是否是CGLIB代理的属性,是否在忽略依赖类型里面,是否是指定的忽略依赖接口。
- 属性填充值里面不包含对应的属性名称。
- 属性不是简单类型的属性。
看看isSimpleProperty方法是如何判断简单属性的:
public static boolean isSimpleProperty(Class<?> type) {
Assert.notNull(type, "'type' must not be null");
return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}调用了isSimpleValueType方法,并且不是数组。
重点看看isSimpleValueType方法:
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}非Void类型,Java中的原生类型,原生类型的包装类型,Enum、CharSequence、Number、Date、Temporal、URI、URL、Locale和Class都是简单类型。
不是这些类型,就可能是Java中的引用类型了,需要获取bean实例的。
3 autowireByType方法
上面已经介绍了autowireByName方法的主要流程,下面重点看看autowireByType方法。
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取用户自定义的类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//获取非简单属性名称数组
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历非简单属性名称数组
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
//排除Object对象类型的属性,意义不大
if (Object.class != pd.getPropertyType()) {
//获取指定的setter方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//根据类型解析指定beanName的属性所匹配的值,
//并把解析到的属性名存储在autowiredBeanNames中。
//当属性存在多个封装bean时,如 @Autowired List<Bean> beans,会找到所有的匹配Bean 类型的bean并将其注入。
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
//将属性名称和bean实例添加到集合中
pvs.add(propertyName, autowiredArgument);
}
//遍历autowiredBeanNames集合
for (String autowiredBeanName : autowiredBeanNames) {
//将bean的依赖关系注册到Spring容器
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
//清空autowiredBeanNames集合
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}autowireByType方法的主要流程如下:

autowireByType方法中通过getCustomTypeConverter方法,可以获取到用户自定义的类型转换器。
通过resolveDependency方法,根据类型找到相对应的bean实例集合,然后将bean的依赖关系注册到Spring容器。
其中resolveDependency方法的逻辑非常复杂,在这里就不过多展开了,感兴趣的小伙伴,可以找我私聊。
4. postProcessProperties方法
接下来,看看第1章中提到的InstantiationAwareBeanPostProcessor接口的postProcessProperties方法。
目前有不少类实现了InstantiationAwareBeanPostProcessor接口:

其中有我们耳熟能详的AutowiredAnnotationBeanPostProcessor类。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
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;
}它里面的逻辑很简单,通过findAutowiringMetadata方法获取@Autowired注解定义的元数据。
而后通过inject方法,将bean实例注入到对应的属性上。
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
//如果元数据是字段
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
//直接通set方法注入bean
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
//如果元数据是方法,比如setter方法
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
//调用比如setter方法注入bean
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}后面会有@Autowired注解原理的专题,敬请期待。
未完待续。。。