Spring IOC(二)依赖查找
Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html)
Spring BeanFactory 的三个重要的实现类功能如下:
AbstractBeanFactory
实现了 BeanFactory、 HierarchicalBeanFactory、ConfigurableBeanFactory 三个接口,最终要的是实现了 getBean(beanName) 查找的接口,但最重要的一个模板方法 createBean 委托给子类完成。AbstractAutowireCapableBeanFactory
实现了 AutowireCapableBeanFactory 接口,也就是依赖注入。同时实现了 crcreateBean(beanName, mbd, args) 的三个重要过程:实例化(createBeanInstance)、依赖注入(populateBean)、初始化(initializeBean)。其中依赖注入又分为 beanName 和 type 二种,其中名称查找很简单,而类型查找就复杂了很多。Spring 将类型查找委托给了子类的 resolveDependency 完成。DefaultListableBeanFactory
实现了 ConfigurableListableBeanFactory、BeanDefinitionRegistry 两个接口,提供了 Bean 和 BeanDefinition 查找注册的功能。 这个类一个很重要的功能是实现了模板方法 resolveDependency,这样就可以根据类型查找依赖。
在 populateBean(beanName, mbd, bw) 中可以看到有两种 bean 的查找方法:名称查找和类型查找,下面我们来分析一下这两种查找方式。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
}
一、名称查找 - autowireByName
毫无疑问,直接从 BeanFactory 中取出这个 bean 就可以了。
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
}
}
}
二、类型查找 - autowireByType
autowireByType 相比 autowireByName 就复杂多了,不过 autowireByType 直接委托给 resolveDependency 方法了,
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);
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// 类型查找时允许对 FactoryBean 提前实例化对象,大部分情况一都是 true。
// 至于为什么实现了 PriorityOrdered 接口的 bean 要排除,以后再研究一下???
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 核心代码就这一句,类型查找委托给了子类的 resolveDependency 完成
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(ex);
}
}
}
resolveDependency(desc, beanName, autowiredBeanNames, converter)
可以说是 AbstractAutowireCapableBeanFactory 最重要的模板方法了,子类 DefaultListableBeanFactory 进行了实现,作用就是根据类型查找依赖。
三、依赖查找 - resolveDependency
3.1 入口 - resolveDependency
先解释一下 resolveDependency 这个方法的四个参数:
-
descriptor
DependencyDescriptor 这个类实现了对字段、方法参数、构造器参数的进行依赖注入时的统一访问方式,你可以简单的认为是对这三种类型的封装。 -
requestingBeanName
外层的 beanName -
autowiredBeanNames
根据类型查找可能有多个,autowiredBeanNames 就是指查找到的 beanName 集合,Spring 支持 Array、Map、Collection 的注入。 -
typeConverter
类型转换器,BeanWrapper 自己就是一个转换器。
@Override
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
resolveDependency 方法将最重要的实现委托给了 doResolveDependency 完成。这里有两个类需要简单的说明一下:ParameterNameDiscovery 和 AutowireCandidateResolver。
-
ParameterNameDiscovery
这个类用于查找方法的参数的名称,默认的实现有 StandardReflectionParameterNameDiscoverer。详见:<> -
AutowireCandidateResolver
策略接口,对特定的依赖,这个接口决定一个特定的 BeanDefinition 是否满足作为自动绑定的备选项。
3.2 findAutowireCandidates
在分析 doResolveDependency 方法之前,先看一下 findAutowireCandidates,这个方法是根据类型在容器中查找到所有可用的 bean。
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 1. 根据类型查找父子容器中所有可用的 beanName,调用 getBeanNamesForType 方法。
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
// 2. 先查找 resolvableDependencies 中的依赖,外部扩展使用,先忽略
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
// 可能为一个 ObjectFactory 对象,调用 getObject 获取真实的对象
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 3. 先将合法的添加进去。eg: isSelfReference(”beanName“, ”&beanName“)=true
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 4. 没有时进行回退操作,如 @Autowire 回退到名称
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
参考:
1 . 《Spring各种依赖注入注解的区别》:https://blog.csdn.net/gaohe7091/article/details/39319363
每天用心记录一点点。内容也许不重要,但习惯很重要!