@Autowired常用的就是属性注入和构造方法注入
大体的逻辑是这样的
- 通过反射查找bean的class下所有注解了@Autowired的字段和方法
- 获取到字段,通过getBean(字段)获取到对应bean,然后再通过反射调用field的set将bean注入
@Autowired源码分析
AutowiredAnnotationBeanPostProcessor类
该类是@Autowired的具体实现类,先预览一下方法
发现实际有机会介入bean的创建操作只有可能是后置处理器,用于后置处理的有3个方法,其中一个过时不用,分别是postProcessMergedBeanDefinition、postProcessProperties后置处理,我们看一下这两个方法的具体代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }
@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; }
|
首先找出所有注解了@Autowired的属性或者方法,然后进行注入,当然postProcessMergedBeanDefinition后置处理器的调用肯定是在postProcessProperties之前的,我们先回顾一下bean的创建流程
1.查找所有@Autowired
1 2
| InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); 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; }
|
可以看到spring依然在用缓存的方式提高性能,buildAutowiringMetadata(clazz)里主要查找所有@Autowired,具体流程:
- 外层
do...while...的村换被用于诋毁查找父类的@Autowired属性或方法
- 通过反射的方式获取到所有属性并循环验证每一个属性是否被
@Autowired注解
- 将查找到包含
Autowired注解的filed封装成AutowiredFieldElement,加入到列表中
- 循环在查找方法上的注解
- 将找到的方法封装成
AutowiredMethodElement,并加入列表
- 将找到的左右元素列表和clazz作为参数生成metadata数据返回
2.注入
1 2
| metadata.inject(bean, beanName, pvs);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }
|
利用for循环,遍历刚刚我们查到的elements列表,进行注入。
这里的element有可能是AutowiredFieldElement类型、或AutowiredMethodElement类型。各自代表@Autowired注解在属性上、以及注解在方法上的两种不同元素
核心语句还是这2句
1 2 3
| ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments);
|