详解Spring中@Autowire,@Value 注解实现原理
Posted Java知音_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解Spring中@Autowire,@Value 注解实现原理相关的知识,希望对你有一定的参考价值。
点击关注公众号,实用技术文章及时了解
来源:blog.csdn.net/u013202238/article/details/107879726
本文主要基于SpringBoot-2.3.3.RELEASE, Spring-5.2.8.RELEASE 讲解.
Spring中@Autowire,@Value 注解实现原理,将这两个注解放到一块讲解主要是他们的实现基本一致。
本文涉及注解:@Autowire、@Value、@Qualifier、@Lazy、@Primary、@javax.annotation.Priority
相关类介绍
如下是几个重要的相关类:
org.springframework.beans.factory.config.BeanPostProcessor
org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.s.beans.factory.annotation.InjectionMetadata.InjectedElement
org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement
org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
BeanPostProcessor
BeanPostProcessor是一个接口类,所有的bean在初始时期都会经过这个后置处理器,主要提供如下两个接口方法,
public interface BeanPostProcessor
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
return bean;
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
return bean;
1、postProcessBeforeInitialization方法在bean初始化方法之前执行.例如bean实现了InitializingBean接口,会在InitializingBean#afterPropertiesSet
方法之前执行。(不完全是这样,因为要看创建bean时,某个BeanPostProcessor实现类是否已经注册)
对于BeanPostProcessor#postProcessBeforeInitialization
是否在@PostConstruct注解的初始化方法之前执行,这是不确定的,因为@PostConstruct初始化方法的执行是通过InitDestroyAnnotationBeanPostProcessor
实现,并且InitDestroyAnnotationBeanPostProcessor通过重写BeanPostProcessor#postProcessBeforeInitialization
实现@PostConstruct功能,CommonAnnotationBeanPostProcessor通过继承InitDestroyAnnotationBeanPostProcessor
拥有了相同的能力,因此要看BeanPostProcessor 实现类被注册的顺序才能决定是否优先于@PostConstruct注解的方式执行。
2、postProcessAfterInitialization 方法在bean的初始化方法之后执行。
3、BeanPostProcessor 的子类接口如下UML图
4、AbstractAutowireCapableBeanFactory#initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
源码如下:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
if (System.getSecurityManager() != null)
AccessController.doPrivileged((PrivilegedAction<Object>) () ->
invokeAwareMethods(beanName, bean);
return null;
, getAccessControlContext());
else
//判断是否实现了Aware接口,执行子类接口方法,
//此时只有:BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic())
//调用BeanPostProcessor#postProcessBeforeInitialization
//ApplicationContextAwareProcessor#postProcessBeforeInitialization
//实现EnvironmentAware,..ApplicationContextAware等Aware的回调.
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
try
//如果bean实现了InitializingBean接口则执行接口的afterPropertiesSet方法
invokeInitMethods(beanName, wrappedBean, mbd);
catch (Throwable ex)
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
if (mbd == null || !mbd.isSynthetic())
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
MergedBeanDefinitionPostProcessor
@Autowire,@Value 的查找 就是AutowiredAnnotationBeanPostProcessor
通过重写该方法实现
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
default void resetBeanDefinition(String beanName)
BeanDefinition主要封装了bean的类信息,例如是否是单实例(Singleton),初始化方法名,依赖的bean名称等等。
在bean对象被创建之前,如果一个bean的BeanDefinition是一个子类,会先合并父类BeanDefinition,最终返回一个合并后的RootBeanDefinition,MergedBeanDefinitionPostProcessor
则是Spring提供给开发的接口,便于对合并后的RootBeanDefinition做自定义修改。在调用AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
时回调MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
方法。扩展:40 个 SpringBoot 常用注解
InstantiationAwareBeanPostProcessor
看注释
@Autowire,@Value 的赋值 就是AutowiredAnnotationBeanPostProcessor
通过重写postProcessProperties方法实现
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor
//创建bean对象实例之前执行
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException
return null;
//创建bean对象实例之后执行
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException
return true;
//用于给bean对象中的成员属性赋值
//@Autowire,@Value的赋值就是AutowiredAnnotationBeanPostProcessor通过重写该方法实现
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException
return null;
@Deprecated //标记为过时
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException
return pvs;
AutowiredAnnotationBeanPostProcessor
@Autowire,@Value,@Lookup等注解功能都是由AutowiredAnnotationBeanPostProcessor
实现,在本文主要讲解@Autowire,@Value注解功能实现原理。
AutowiredAnnotationBeanPostProcessor
的继承关系如下:
AutowiredAnnotationBeanPostProcessor
的构造方法如下:主要定义了@Autowire,@Value两个注解是过滤目标bean的条件,如果bean中的Field、Method被标记这两个注解,则需要为其注入对应的bean或者属性值。
public AutowiredAnnotationBeanPostProcessor()
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
catch (ClassNotFoundException ex)
// JSR-330 API not available - simply skip.
在实现@Autowire,@Value功能的过程中,AutowiredAnnotationBeanPostProcessor
主要起到两个作用。
1、重写MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
方法,反射遍历beanClass中的所有Field和Method,查找bean中标记有@Autowire,@Value的Field、Method,封装到org.springframework.beans.factory.annotation.InjectionMetadata
中。
保存在成员变量private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
中。
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
源码:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
findAutowiringMetadata方法内部会调用到AnnotationUtils#isCandidateClass(Class<?>, Class<? extends Annotation>)
用于判断某个类是否可能 被标记指定的某个注解。源码如下:
public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType)
return isCandidateClass(clazz, annotationType.getName());
public static boolean isCandidateClass(Class<?> clazz, String annotationName)
//如果注解所在包是java开头,任何类上都可能标记这个注解
if (annotationName.startsWith("java."))
return true;
//注解所在包不是java开头的情况
//可以认为是自定义注解,例如Spring的@Service @Autowired @Value 对Spring来说就是其自定义注解
//如果类的包是以java开头,则不可能标记自定义的注解
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz))
return false;
return true;
AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)
static boolean hasPlainJavaAnnotationsOnly(Class<?> type)
return (type.getName().startsWith("java.") || type == Ordered.class);
2、重写InstantiationAwareBeanPostProcessor#postProcessProperties
方法,遍历injectionMetadataCache中的InjectionMetadata,调用org.springframework.beans.factory.annotation.InjectionMetadata#inject
方法,为bean的@Autowire和@value属性字段赋值。
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;
InjectionMetadata里面有个abstract内部类InjectionMetadata.InjectedElement
,主要用于给Field或者Method赋值。
AutowiredAnnotationBeanPostProcessor
中有两个私有内部类分别继承了InjectedElement。
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement
: 通过反射给Field赋值.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
: 通过反射调用setter Method赋值.
AutowiredAnnotationBeanPostProcessor.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)
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
value = resolveFieldValue(field, bean, beanName);
if (value != null)
//反射赋值
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
源码:
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName)
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();
Object value;
try
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;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1)
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType()))
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
return value;
方法内部调用的beanFactory.resolveDependency
(默认DefaultListableBeanFactory)整体逻辑大概如下:
1.判断Filed或者Method上是否有@Lazy注解,如果存在则创建代理,实现懒加载。
2.不是懒加载,则判断是否存在@Value注解,如果存在则获取value值,最后通过PropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class<T>, boolean)
解析属性值(其实就是ConfigurableEnvironment中封装的MutablePropertySources集合),获取到属性值之后还会通过SpringEL进行一次解析。解析之后再由SimpleTypeConverter对象进行一次数据类型转换,转为Filed所需要的类型返回.
3.如果不存在@Value注解,则是根据@Autowire注入bean, 从DefaultListableBeanFactory中变量所有的beanName,判断对象类型是否和所需的相同,相同则保存beanName到List集合中(一个相同的接口可能出现多个实现类,所以用集合),
遍历beanNames,判断每个bean是否符合要求,如果存在@Qualifier会判断名称是否匹配,匹配则获取对应bean对象。如果没有@Qualifier注解,则获取全部的bean对象,封装到Map中。
如果Map中存在多个实例对象,再判断查找带有@Primary注解的实现类,返回对象。同类型实现@Primary只能有一个
如果Map中存在多个实例对象,但是没有@Primary注解,再比较是否有
@javax.annotation.Priority
注解,选择优先高的返回,值越小优先级越高。根据名称匹配
不符合以上规则,则抛出异常信息,出现多个bean实现。
Spring中依赖注入Bean的匹配逻辑如下
DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor)
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null)
return primaryCandidate;
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null)
return priorityCandidate;
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet())
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName()))
return candidateName;
return null;
推荐
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!
以上是关于详解Spring中@Autowire,@Value 注解实现原理的主要内容,如果未能解决你的问题,请参考以下文章
spring源码分析@Autowire注入补充,@Resource源码分析
Spring 基于自动装配的依赖注入详解 [自动装配模式搞不懂?来看就完了!!!][autowire 属性值详解][自动装配的 6 种模式]