一、Autowired注解的原理的概览
我们都知道一个Bean的大致生命周期有这几个阶段,实例化--> 属性填充 --> 初始化 --> 销毁回调
其中Autowired作用的时间就是在属性填充阶段,而且是通过AutowiredAnnotation BeanPostProcessor类进行处理的。注入的整体流程如下:
二、一步步分析Autowired的源码
AutowiredAnnotationBeanPostProcessor的postProcessProperties方法是我们此次分析的入口。其代码如下:
@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(用来查找标注有autowried注解的字段和方法)、metadata.inject(基于已经找到需要注入的信息来去spring容器中获取到对应的bean进行注入)。下面将重点分析这两个方法
1、findAutowiringMetadata方法详解
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 首先从缓存中获取当前需要进行注入的元数据,缓存的key为bean的名称(如果有),否则为类名
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 判断是否刷新的条件是:1、metadata为null , 2、要注入的目标类跟当前入参中的clazz不是同一个类型
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
// 这里使用双重检查机制保证没有二次去出发构建自动注入的方法
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 构建需要自动的元数据类
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
上面的方法中我们优先从缓存中去获取自动注入的对象,如果缓存中有说明之前已经创建过了,直接进行返回,没有的化执行创建动作。接下来我们重点关注buildAutowiringMetadata方法
1.1 buildAutowiringMetadata方法解析
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 1、查找所有的标注了@Autowired的字段,生成AutowiredFieldElement对象,添加到currElements集合
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 2、查找所有的标注了@Autowired的方法,生成AAutowiredMethodElement对象,添加到currElements集合
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
// 3、向上递归父类,知道找到Object为止
while (targetClass != null && targetClass != Object.class);
// 4、 基于之前创建的AutowiredElements生成InjectionMetadata实例
return InjectionMetadata.forElements(elements, clazz);
}
该方法中主要做了三件事,
1、查找所有的标注了@Autowired的字段,生成AutowiredFieldElement对象,添加到currElements集合
2、查找所有的标注了@Autowired的方法,生成AAutowiredMethodElement对象,添加到currElements集合
3、 基于前两步创建的AutowiredElements生成InjectionMetadata实例
至此我们已经生成了InjectionMetadata对象,那么我们接下来分析下metadata.inject方法。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 1、 checkConfigMembers 方法执行后会设置上checkedElements
Collection<InjectedElement> checkedElements = this.checkedElements;
// 2、代迭代进行赋值的元素 优先获取checkedElements里面的集合,没有的时候使用injectedElements里面的
// 两个集合的区别事第一个集合排除哪些由外部进行配置字段或者方法
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
// 3、执行具体InjectedElement的注入方法
element.inject(target, beanName, pvs);
}
}
}
该方法的主要做了以下两件事,其中最主要的执行具体的InjectedElement 的inject方法。
1、从当前对象获取真正需要的执行依赖注入的元素,优先取优先获取checkedElements里面的集合,没有的时候使用injectedElements里面的 ,两个集合的区别事第一个集合排除哪些由外部进行配置字段或者方法
2、执行执行具体InjectedElement的注入方法
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
// 1、这里默认是false
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
// 2、根据获取到字段、原始类及bean的名称从BeanFactory中获取到依赖的bean对象
value = resolveFieldValue(field, bean, beanName);
}
// 3、通过反射设置bean的属性值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
这里inject的核心就是获取解析出来具体Bean的值,并且通过反射将值设置进去。接下里就核心关注下org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue方法
2.1 resolveFieldValue方法解析
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
// ... 省略其他非核心代码
try {
// 1、从beanFactory中解析出对应的bean对象
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
// 2、 注册依赖的bean对象
registerDependentBeans(beanName, autowiredBeanNames);
// .... 省略其他非核心代码
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
该方法中的主要是两个核心方法,
2.1.1从beanFactory中解析出对应的bean对象
org.springframework.beans.factory.config.AutowireCapableBeanFactory#resolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set<java.lang.String>, org.springframework.beans.TypeConverter)
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
此段代码核心要关注的是doResolveDependency方法,接下来具体看下其逻辑:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// ... 省略其他代码
// 从这里开始,合适的bean只有一个
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// @Autowired中 required是否标记为true,默认为true
if (isRequired(descriptor)) {
// 抛出没有对应的bean的异常信息
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 当满足条件的Bean超过一个的时候,需要精确定位到一个
if (matchingBeans.size() > 1) {
// 获取自动注入中最合适注入的那个Bean的名称,该名称的查找规则是:1、 标注了@Primary的类 2、实现order接口中优先级最高的那个
// 3、字段名称或者方法名称跟bean名称相同的那个
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
//超过一个的时候就进行抛出异常处理
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}