相关源码注释
ApplicationContext
Spring 5 DefaultResourceLoader 源码注释
Spring 5 AbstractApplicationContext 源码注释
BeanFactory
Spring 5 SimpleAliasRegistry 源码注释
Spring 5 DefaultSingletonBeanRegistry 源码注释
Spring 5 FactoryBeanRegistrySupport 源码注释
Spring 5 AbstractBeanFactory 源码注释
Spring 5 AbstractAutowireCapableBeanFactory 源码注释
Spring 5 DefaultLisbaleBeanFactory 源码注释
isAutowireCandidate(String , DependencyDescriptor )
确定指定的bean定义是否可以自动注入:
- 获取此BeanFactory的自动装配候选解析器
- 交由isAutowireCandidate(String, DependencyDescriptor, AutowireCandidateResolver) 处理并将结果返回出去
/**
* 确定指定的bean定义是否可以自动注入
* @param beanName the name of the bean to check -- 要检查的bean名
* @param descriptor the descriptor of the dependency to resolve -- 要解决的依赖项的描述符
* @return 是否应将bean视为自动装配候选对象
* @throws NoSuchBeanDefinitionException 如果没有给定名称的bean
*/
@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}
isAutowireCandidate(String, DependencyDescriptor, AutowireCandidateResolver)
确定指定的bean定义是否可以自动注入:
- 解决beanName存在于该工厂的情况:
- 去除开头的’&'字符,返回剩余的字符串作为转换后的Bean名称【全类名】【变量 beanDefinitionName】
- 如果工厂包含beanDefinitionName得BeanDefinition对象,就确定beanDefinitionName的合并后RootBeanDefinition 是否符合自动装配候选条件,以注入到声明匹配类型依赖项的其他bean中并将结果返回出去
- 如果beanName在该BeanFactory的单例对象的高速缓存Map集合【DefaultSingletonBeanRegistry.singletonObjects】中, 获取beanName的Class对象,从而构建出RootBeanDefinition实例对象,最后确定该RootBeanDefinition实例对象是否符合自动装 配候选条件,以注入到声明匹配类型依赖项的其他bean中并将结果返回出去
- 解决beanName存在于该工厂的父工厂的情况:
- 获取父工厂【变量 parent】
- 如果父工厂是DefaultListableBeanFactory的实例对象,递归交由父工厂的该方法处理并将结果返回
- 如果父工厂是ConfigurableListableBeanFactory的实例对象,就递归交由父工厂的isAutowireCandidate(String, DependencyDescriptor) 进行处理并将结果返回出去
- 如果上面各种情况都没有涉及,默认是返回true,表示应将bean视为自动装配候选对象
/**
* <p>确定指定的bean定义是否可以自动注入 </p>
* Determine whether the specified bean definition qualifies as an autowire candidate,
* to be injected into other beans which declare a dependency of matching type.
* <p>确定指定的bean定义是否符合自动装配候选条件,以注入到声明匹配类型依赖项的其他bean中。</p>
* @param beanName the name of the bean definition to check
* -- 要检查的beanDefinition名称
* @param descriptor the descriptor of the dependency to resolve
* -- 要解析的依赖项的描述符
* @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
* -- AutowireCandidateResolver用于实际的解析算法
* @return whether the bean should be considered as autowire candidate
* -- 是否应将bean视为自动装配候选对象
* @see #isAutowireCandidate(String, RootBeanDefinition, DependencyDescriptor, AutowireCandidateResolver)
*/
protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
throws NoSuchBeanDefinitionException {
//去除开头的'&'字符,返回剩余的字符串作为转换后的Bean名称【全类名】
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
//如果工厂包含beanDefinitionName得BeanDefinition对象
if (containsBeanDefinition(beanDefinitionName)) {
//确定beanDefinitionName的合并后RootBeanDefinition是否符合自动装配候选条件,以注入到声明匹配类型依赖项的其他bean中
// 并将结果返回出去
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver);
}
//这里应该是直接调用registerSingeton(String,Object)方法的情况
//如果beanName在该BeanFactory的singletonObjects【单例对象的高速缓存Map集合】中
else if (containsSingleton(beanName)) {
//获取beanName的Class对象,从而构建出RootBeanDefinition实例对象,最后确定该RootBeanDefinition实例对象是否符合自动装
// 配候选条件,以注入到声明匹配类型依赖项的其他bean中并将结果返回出去
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
//获取父工厂
BeanFactory parent = getParentBeanFactory();
//如果父工厂是DefaultListableBeanFactory的实例对象
if (parent instanceof DefaultListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
// 在该工厂中找不到BeanDefinition ->委托给父对象
// 递归交由父工厂处理并将结果返回
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
}
//如果父工厂是ConfigurableListableBeanFactory的实例对象
else if (parent instanceof ConfigurableListableBeanFactory) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
// 如果没有DefaultLisableBeanFactory,则无法传递解析器
// 这个时候,由于ConfigurableListableBeanFactory没有提供isAutowireCandidate(String, DependencyDescriptor, AutowireCandidateResolver)的
// 重载方法,所以递归交由父工厂的isAutowireCandidate(String, DependencyDescriptor)进行处理并将结果返回出去
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
}
else {
//如果上面各种情况都没有涉及,默认是返回true,表示应将bean视为自动装配候选对象
return true;
}
}
isAutowireCandidate(String, RootBeanDefinition, DependencyDescriptor, AutowireCandidateResolver)
确定mbd可以自动注入到descriptor所包装的field/methodParam中:
- 去除开头的’&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】【变量 beanDefinitionName】
- 为mdb解析出对应的bean class对象
- 如果mbd指明了引用非重载方法的工厂方法名称【RootBeanDefinition.isFactoryMethodUnique】 且 mbd还没有缓存 用于自省的唯一工厂方法候选【RootBeanDefinition.factoryMethodToIntrospect】:如果可能,新建一个ConstuctorResolver 对象来解析mbd中factory方法
- 根据mbd,beanName,beanDefinitionName的别名构建一个BeanDefinitionHolder实例,交给resolver进行判断, 是否可以自动注入并将结果返回出去。resolver的判断依据还是看mdb的AbstractBeanDefinition.isAutowireCandidate()结果。
/**
* <p>
* 确定mbd可以自动注入到descriptor所包装的field/methodParam中
* </p>
* Determine whether the specified bean definition qualifies as an autowire candidate,
* to be injected into other beans which declare a dependency of matching type.
* <p>确定指定的bean定义是否符合自动装配候选条件,以注入到声明匹配类型依赖项的其他bean中。</p>
* @param beanName the name of the bean definition to check -- 要检查的beanDefinition名
* @param mbd the merged bean definition to check -- 要检查的合并后BeanDefinition
* @param descriptor the descriptor of the dependency to resolve -- 要解析的依赖项的描述符
* @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
* -- AutowireCandidateResolver用于实际的分析算法
* @return whether the bean should be considered as autowire candidate
* -- 是否应将bean视为自动装配候选对象
*/
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
//去除开头的'&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
//为mdb解析出对应的bean class对象
resolveBeanClass(mbd, beanDefinitionName);
//如果mbd指明了引用非重载方法的工厂方法名称 且 mbd还没有缓存用于自省的唯一工厂方法候选
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
//如果可能,新建一个ConstuctorResolver对象来解析mbd中factory方法
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
//根据mbd,beanName,beanDefinitionName的别名构建一个BeanDefinitionHolder实例,交给resolver进行判断
// 是否可以自动注入。resolver的判断依据还是看mdb的isAutowireCandidate()结果。
return resolver.isAutowireCandidate(
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
}
BeanFactoryUtils.transformedBeanName(beanName);
去除开头的’&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】:
- 如果name为null,抛出异常
- 如果name不是以’&'开头,就直接返回
- 从具有FactoryBean前缀的名称缓存到剥离的名称的ConcurrentHashMap【transformedBenaNameCache】 中获取bean名对应的转换后的名称并返回
- 获取不到时就构建一个:从name的开头位置去掉’&’,再重新检查是否还是以’&‘开头,是的话就再截直到没有出现’&'开头为止。所得到 的字符串就是Bean名称【可能是全类名】
/**
* Cache from name with factory bean prefix to stripped name without dereference.
* <p>从具有FactoryBean前缀的名称缓存到剥离的名称,而无需取消引用</p>
* @since 5.1
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();
/**
* <p>去除开头的'&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】
* </p>
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
* <p>返回实际的bean名称,删除工厂取消引用前缀(如果有的话,还删除重复的
* 工厂前缀(如果找到))</p>
* <p>用于获取以'&'开头的name对应的bean名,如果bean不是'&'开头,就直接返回该name</p>
* @param name the name of the bean - bean名
* @return the transformed name - 转换后的名称
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
public static String transformedBeanName(String name) {
//如果bean名为null,抛出异常
Assert.notNull(name, "'name' must not be null");
//如果bean名不是以'&'开头,就直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
//从transformedBenaNameCache中获取bean名对应的转换后的名称
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
//从beanName的开头位置去掉'&',并重新赋值给beanName,再重新检查是还是以'&'开头,是的话就再截
// 知道开头不是以'&'开头后,加入到transformedBeanNameCache中
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}