Spring IoC @Autowired 注解详解
前言
本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT
版本。因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析。
我们平时使用 Spring 时,想要 依赖注入 时使用最多的是 @Autowired
注解了,本文主要讲解 Spring 是如何处理该注解并实现 依赖注入 的功能。
正文
首先我们看一个测试用例:
User
实体类:
public class User {private Long id;private String name; // 省略 get 和 set 方法}
测试类:
public class AnnotationDependencyInjectTest {/** * @Autowired 字段注入 */@Autowiredprivate User user;private City city;/** * @Autowired 方法注入 */@Autowiredpublic void initCity(City city) {this.city = city;}public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(AnnotationDependencyInjectTest.class);context.refresh();AnnotationDependencyInjectTest bean = context.getBean(AnnotationDependencyInjectTest.class);// @Autowired 字段注入System.out.println(bean.user);// @Autowired 方法注入System.out.println(bean.city);UserHolder userHolder = context.getBean(UserHolder.class);// @Autowired 构造器注入System.out.println(userHolder.getUser());context.close();}@Beanpublic User user() {User user = new User();user.setId(1L);user.setName("leisurexi");retu user;}@Beanpublic City city() {City city = new City();city.setId(1L);city.setName("北京");retu city;}/** * @Autowired 构造函数注入 */static class UserHolder {private User user;@Autowiredpublic UserHolder(User user) {this.user = user;}public User getUser() {retu user;}public void setUser(User user) {this.user = user;}}}
上面分别展示了 @Autowired
注解的字段注入和方法注入,下面我们开始分析 Spring 是如何实现的。
首先使 @Autowired
注解生效的一个关键类是 AutowiredAnnotationBeanPostProcessor
,该类实现了 InstantiationAwareBeanPostProcessorAdapter
抽象类;该抽象类就是一个适配器的作用提供了接口方法的默认实现,InstantiationAwareBeanPostProcessorAdapter
又实现了 SmartInstantiationAwareBeanPostProcessor
接口,同时实现该接口的 determineCandidateConstructors()
方法可以指定 bean
的候选构造函数;然后 SmartInstantiationAwareBeanPostProcessor
接口又继承了 InstantiationAwareBeanPostProcessor
接口,该接口提供了 bean
实例化前后的生命周期回调以及属性赋值前的后置处理方法,@Autowired
注解的属性注入就是通过重写该接口的 postProcessProperties()
实现的。这两个接口都在 Spring IoC bean 的创建 一文中有介绍过。下面我们看一下 AutowiredAnnotationBeanProcessor
的继承关系图:
关于 AutowiredAnnotationBeanPostProcessor
这个后置处理器是怎么加入到 beanFactory
中的,我们在 Spring IoC component-scan 节点详解 一文中介绍过主要是通过 AnnotationConfigUtils#registerAnnotationConfigProcessors()
实现的。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {// 省略其他代码...// 注册用于处理@Autowired、@Value、@Inject注解的后置处理器if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// 省略其他代码...}
属性和方法注入
AutowiredAnnotationBeanPostProcessor
中跟属性注入有关的方法有两个:postProcessMergedBeanDefinition
和 postProcessPropertyValues
。
前者是 MergedBeanDefinitionPostProcessor
接口中的方法,定义如下:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {/** * 对指定bean的BeanDefinition合并后的处理方法回调 */void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);// 省略其他代码...}
后者是 InstantiationAwareBeanPostProcessor
接口中的方法,定义如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {/** * Bean 实例化后属性赋值前调用,PropertyValues 是已经封装好的设置的属性值,返回 {@code null} 继续 * 使用现有属性,否则会替换 PropertyValues。 */@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {retu null;}// 省略其他代码...}
关于这两个方法的调用时机,可以查看Spring IoC bean 的创建和Spring IoC 属性赋值阶段。
bean 合并后处理
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
首先执行的是 postProcessMergedBeanDefinition()
方法。
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {// 寻找需要注入的字段或方法,并封装成 InjectionMetadata,见下文详解InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);// 检查元数据中的注解信息metadata.checkConfigMembers(beanDefinition);}
InjectionMetadata
就是注入的元信息描述,主要字段如下:
public class InjectionMetadata {// 需要依赖注入的目标类private final Class<?> targetClass;// 注入元素的集合private final Collection<InjectedElement> injectedElements;// 忽略其它代码}
InjectedElement
就是注入的元素,主要字段如下:
public abstract static class InjectedElement {// 注入的属性或方法protected final Member member;// 需要注入的是否是字段protected final boolean isField;}
查找需要注入的字段或方法
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());// 首先从缓存中获取InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);// 判断是否需要刷新,即metadata为null或者metadata中存储的targetClass和当前clazz不等if (InjectionMetadata.needsRefresh(metadata, clazz)) {// 这里相当于是一个double check,防止多线程出现的并发问题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);}}}// 返回注入元信息retu metadata;}
创建需要注入的元信息
AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {retu InjectionMetadata.EMPTY;}// 判断当前类或其字段或其方法是否标注了autowiredAnnotationTypes中的注解,没有的话直接返回空的List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();// 遍历targetClass中的字段ReflectionUtils.doWithLocalFields(targetClass, field -> {// 获取field上的@Autowired注解信息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);}retu;}// 获取@Autowired注解中的required属性boolean required = determineRequiredStatus(ann);// 将装成AutowiredFieldElement添加进currElementscurrElements.add(new AutowiredFieldElement(field, required));}});// 遍历targetClass中的方法ReflectionUtils.doWithLocalMethods(targetClass, method -> {// 找到桥接方法Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);// 判断方法的可见性,如果不可见则直接返回if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {retu;}// 获取method上的@Autowired注解信息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);}retu;}// 方法注入没有参数就违背了初衷,就是在脱裤子放屁if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation should only be used on methods with parameters: " + method);}}// 获取@Autowired注解中的required属性boolean required = determineRequiredStatus(ann);// 将方法和目标类型封装成属性描述符PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);// 封装成AutowiredMethodElement添加进currElementscurrElements.add(new AutowiredMethodElement(method, required, pd));}});// 将currElements整个添加进elementselements.addAll(0, currElements);// 获取targetClass的父类,进行下一次循环targetClass = targetClass.getSuperclass();}// 当targetClass为空或者targetClass等于Object.class时会退出循环while (targetClass != null && targetClass != Object.class);// 将elements和clazz封装成InjectionMetadata返回retu InjectionMetadata.forElements(elements, clazz);}
上面代码中的 findAutowiredAnnotation()
就是在遍历 autowiredAnnotationTypes
属性,看字段或者方法上的注解是否存在于 autowiredAnnotationTypes
中,或者其派生注解,找到第一个就返回,不会再继续遍历了。
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);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.}}}
从 AutowiredAnnotationBeanPostProcessor
类的构造函数中,我们可以发现 autowiredAnnotationTypes
默认添加了 @Autowired
、@Value
以及 @Inject
(在 JSR-330 的jar包存在于当前环境时)。
至此,使用 @Autowired
修饰的字段和方法已经封装成 InjectionMetadata
并放在 injectionMetadataCache
缓存中,便于后续使用。
bean 属性的后置处理
AutowireAnnotationBeanPostProcessor#postProcessProperties
postProcessMergedBeanDefinition()
调用后 bean
就会进行实例化接着调用 postProcessProperties()
。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 获取缓存中的 InjectionMetadataInjectionMetadata 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);}// 返回注入的属性retu pvs;}// InjectMetadata.javapublic void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// 获取检查后的元素Collection<InjectedElement> checkedElements = this.checkedElements;// 如果checkedElements不为空就使用checkedElements,否则使用injectedElementsCollection<InjectedElement> elementsToIterate =(checkedElements != null ? checkedElements : this.injectedElements);if (!elementsToIterate.isEmpty()) {// 遍历elementsToIteratefor (InjectedElement element : elementsToIterate) {if (logger.isTraceEnabled()) {logger.trace("Processing injected element of bean '" + beanName + "': " + element);}// AutowiredFieldElement、AutowiredMethodElement这两个类继InjectionMetadata.InjectedElement// 各自重写了inject方法element.inject(target, beanName, pvs);}}}
字段注入
AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// 强转成Field类型Field field = (Field) this.member;Object value;if (this.cached) {// 如果缓存过,直接使用缓存的值,一般第一次注入都是falsevalue = resolvedCachedArgument(beanName, this.cachedFieldValue);}else {// 构建依赖描述符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();try {// 进行依赖解决,获取符合条件的beanvalue = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}// 加锁synchronized (this) {// 如果没有被缓存if (!this.cached) {// 找到了需要的bean || 该字段是必要的if (value != null || this.required) {// 将依赖描述符赋值给cachedFieldValuethis.cachedFieldValue = desc;// 注册bean的依赖关系,用于检测是否循环依赖registerDependentBeans(beanName, autowiredBeanNames);// 如果符合条件的bean只有一个if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();// beanFactory含有名为autowiredBeanName的bean && 类型是匹配的if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {// 将该属性解析到的bean的信息封装成ShortcutDependencyDescriptor// 之后可以通过调用resolveShortcut()来间接调beanFactory.getBean()快速获取beanthis.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}else {this.cachedFieldValue = null;}// 缓存标识设置为truethis.cached = true;}}}// 如果找到了符合的bean,设置字段可访问,利用反射设置值if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}
上面代码中的 beanFactory.resolveDependency()
在 Spring IoC bean 的创建 一文中有介绍过,这里不再赘述;同样 registerDependentBeans()
最终会调用 DefaultSingletonBeanRegistry.registerDependentBean()
,该方法在 Spring IoC bean 的创建 一文中有介绍过,这里也不再赘述。
方法注入
AutowiredMethodElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// 检查是否需要跳过if (checkPropertySkipping(pvs)) {retu;}// 强转成Method类型Method method = (Method) this.member;Object[] arguments;if (this.cached) {// 如果缓存过,直接调用beanFactory.resolveDependency()返回符合的beanarguments = resolveCachedArguments(beanName);}else {// 获取参数数量int argumentCount = method.getParameterCount();arguments = new Object[argumentCount];// 创建依赖描述符数组DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];// 记录用于自动注入bean的名称集合Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);Assert.state(beanFactory != null, "No BeanFactory available");// 获取类型转换器TypeConverter typeConverter = beanFactory.getTypeConverter();// 遍历参数for (int i = 0; i < arguments.length; i++) {// 将方法和参数的下标构建成MethodParameter,这里面主要记录了参数的下标和类型MethodParameter methodParam = new MethodParameter(method, i);// 将MethodParameter构建成DependencyDescriptorDependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);currDesc.setContainingClass(bean.getClass());descriptors[i] = currDesc;try {// 进行依赖解决,找到符合条件的beanObject arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);if (arg == null && !this.required) {arguments = null;break;}arguments[i] = arg;}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);}}// 这里跟字段注入差不多,就是注册bean的依赖关系,并且缓存每个参数的ShortcutDependencyDescriptorsynchronized (this) {if (!this.cached) {if (arguments != null) {DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);registerDependentBeans(beanName, autowiredBeans);if (autowiredBeans.size() == argumentCount) {Iterator<String> it = autowiredBeans.iterator();Class<?>[] paramTypes = method.getParameterTypes();for (int i = 0; i < paramTypes.length; i++) {String autowiredBeanName = it.next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]);}}}this.cachedMethodArguments = cachedMethodArguments;}else {this.cachedMethodArguments = null;}this.cached = true;}}}// 找到了符合条件的beanif (arguments != null) {try {// 设置方法可访问,利用反射进行方法调用,传入参数ReflectionUtils.makeAccessible(method);method.invoke(bean, arguments);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}
构造器注入
构造器注入就是通过调用 determineCandidateConstructors()
来返回合适的构造器。
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException {// Quick check on the concurrent map first, with minimal locking.// 首先从缓存中获取Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);// 缓存为空if (candidateConstructors == null) {// Fully synchronized resolution now...// 这里相当于double checksynchronized (this.candidateConstructorsCache) {candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {Constructor<?>[] rawCandidates;try {// 获取beanClass的所有构造函数rawCandidates = beanClass.getDeclaredConstructors();}catch (Throwable ex) {throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);}// 存放标注了@Autowired注解的构造器List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);// 存放标注了@Autowired注解,并且required为true的构造器Constructor<?> requiredConstructor = null;Constructor<?> defaultConstructor = null;for (Constructor<?> candidate : rawCandidates) {// 获取构造器上的@Autowired注解信息MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);if (ann == null) {// 如果没有从候选者找到注解,则尝试解析beanClass的原始类(针对CGLIB代理)Class<?> userClass = ClassUtils.getUserClass(beanClass);if (userClass != beanClass) {try {Constructor<?> superCtor =userClass.getDeclaredConstructor(candidate.getParameterTypes());ann = findAutowiredAnnotation(superCtor);}catch (NoSuchMethodException ex) {// Simply proceed, no equivalent superclass constructor found...}}}if (ann != null) {// 如果requiredConstructor不为空,代表有多个标注了@Autowired且required为true的构造器,此时Spring不知道选择哪个抛出异常if (requiredConstructor != null) {throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " + requiredConstructor);}// 获取@Autowired注解的reuired属性的值boolean required = determineRequiredStatus(ann);if (required) {// 如果当前候选者是@Autowired(required = true),则之前不能存在其他使用@Autowire注解的构造函数,否则抛异常if (!candidates.isEmpty()) {throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " + candidate);}// required为true将当前构造器赋值给requiredConstructorrequiredConstructor = candidate;}// 将当前构造器加入进候选构造器中candidates.add(candidate);}// 没有标注了@Autowired注解且参数长度为0,赋值为默认构造器else if (candidate.getParameterCount() == 0) {defaultConstructor = candidate;}}// 有标注了@Autowired注解的构造器if (!candidates.isEmpty()) {// Add default constructor to list of optional constructors, as fallback.// 没有标注了@Autowired且required为true的构造器if (requiredConstructor == null) {// 默认构造器不为空if (defaultConstructor != null) {// 将默认构造器加入进候选构造器中candidates.add(defaultConstructor);}}// 将候选者赋值给candidateConstructorscandidateConstructors = candidates.toArray(new Constructor<?>[0]);}// 只有1个构造器 && 参数长度大于0(非默认构造器),只能用它当做候选者了else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {candidateConstructors = new Constructor<?>[] {rawCandidates[0]};}// 只有1个构造器 && 参数长度大于0,只能用它当做候选者了else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};}else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {candidateConstructors = new Constructor<?>[] {primaryConstructor};}// 返回一个空的Constructorelse {candidateConstructors = new Constructor<?>[0];}// 缓存候选的构造器this.candidateConstructorsCache.put(beanClass, candidateConstructors);}}}// 如果候选构造器长度大于0,直接返回,否则返回nullretu (candidateConstructors.length > 0 ? candidateConstructors : null);}
关于 SmartInstantiationAwareBeanPostProcessor
接口的调用时机,在 Spring IoC bean 的创建 一文中有介绍过,这里就不再赘述了。
总结
本文主要介绍了 Spring 对 @Autowired
注解的主要处理过程,结合前面的 Spring IoC bean 的加载 和 Spring IoC bean 的创建 以及 Spring IoC 属性赋值阶段 一起看才能更好的理解。
最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring。
作者:leisurexi
来源链接:https://www.cnblogs.com/leisurexi/p/13263542.html
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。