https://www.cnblogs.com/leisurexi/p/13263542.html
https://segmentfault.com/a/1190000038251563

一、Spring依赖注入的方式

1.1、手动注入

1.1.1、使用XML的方式进行Setter方式的注入

  1. public class SpringAction {
  2. // 注入对象springDao
  3. private SpringDao springDao;
  4. // 一定要写被注入对象的set方法
  5. public void setSpringDao(SpringDao springDao) {
  6. this.springDao = springDao;
  7. }
  8. }
  1. <!--配置bean,配置后该类由spring管理-->

1.1.2、构造器注入

这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDaoUser两个参数值传进来:

  1. public class SpringAction {
  2. //注入对象springDao
  3. private SpringDao springDao;
  4. private User user;
  5. }

在XML文件中同样不用的形式,而是使用标签,ref属性同样指向其它标签的name属性:

  1. <!--配置bean,配置后该类由spring管理-->
  2. <bean name="springAction" class="com.bless.springdemo.action.SpringAction">

1.2、 自动注入

1.2.1、XML的自动注入

其实Spring也支持bean的自动注入。在定义bean时我们可以通过bean元素的autowire属性来指定是否需要给当前bean来自动注入其所关联的bean。autowire属性的可选值有四个。

  1. public class Hello {
  2. public Hello(World world) {
  3. }
  4. }
  1. <!-- 通过构造方法按照类型进行自动注入 -->
  2. <bean id="hello" class="com.app.Hello" autowire="constructor"/>

1.2.2、@Autowired自动注入

三、AutowiredAnnotationBeanPostProcessor 类

AutowiredAnnotationBeanPostProcessor是实现@Autowired 功能的主要类,它有一些方法是会用解析 @Autowired 注解并实现自动注入的功能。

3.1、 收集注入元信息

3.1.1、resolveBeforeInstantiation

15-Spring源码-依赖注入(1) - 图1

  • 首先在CreateBean()方法调用 resolveBeforeInstantiation() 方法,执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法
  • 如果postProcessBeforeInstantiation返回Bean实例那么直接返回这个实例,如果返回nul 继续调用doCreateBean

    1. @Override
    2. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    3. throws BeanCreationException {
    4. ...
    5. try {
    6. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    7. // 有机会返回一个代理对象。SPring的扩展点
    8. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    9. if (bean != null) {
    10. return bean;
    11. }
    12. }
    13. // 执行创建Bean的过程
    14. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    15. ...
    16. }
    17. @Nullable
    18. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    19. Object bean = null;
    20. // beforeInstantiationResolved表示该bean实例化前启用实例化后置处理器
    21. // 1、Bean的属性中的beforeInstantiationResolved字段是否为true,默认是false。
    22. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    23. // 2、是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true,程序设置
    24. // 3、Bean的hasInstantiationAwareBeanPostProcessors属性为true,
    25. // 这个属性在Spring准备刷新容器前转换BeanPostProcessors的时候会设置,
    26. // 如果当前Bean实现了InstantiationAwareBeanPostProcessor则这个就会是true。
    27. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    28. Class<?> targetType = determineTargetType(beanName, mbd);
    29. if (targetType != null) {
    30. // 这里就是调用了BeanPost的前置方法
    31. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    32. if (bean != null) {
    33. // 这里就是调用了BeanPost的后置方法
    34. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    35. }
    36. }
    37. }
    38. // 不满足2或者3的时候就会设置为false
    39. mbd.beforeInstantiationResolved = (bean != null);
    40. }
    41. return bean;
    42. }

    hasInstantiationAwareBeanPostProcessors()参考13-Spring源码refresh-registerBeanPostProcessors
    中的代码块3。通过hasInstantiationAwareBeanPostProcessors()方法看有没有InstantiationAwareBeanPostProcessors接口的实现类,如果有,就调用该接口的postProcessBeforeInstantiation方法,如果这个接口有创建返回Bean,再调用BeanPostProcessor接口的postProcessAfterInitialization的方法,这样就完成了Bean的创建。

我们看到如果是在这一阶段通过InstantiationAwareBeanPostProcessor接口产生了Bean返回的话,那其就只会调用BeanPostProcessor接口的postProcessAfterInitialization方法,不会再调用其的例如一些Aware等接口。

如果在上面没有通过InstantiationAwareBeanPostProcessor产生Bean的话,就会接着往下调用doCreateBean(beanName, mbdToUse, args)方法。

通过断点调试, 不难发现, 6个后置处理器中, 满足条件的就三个, 按照执行顺序排列为:

  1. ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
  2. CommonAnnotationBeanPostProcessor
  3. AutowiredAnnotationBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation

  1. @Override
  2. @Nullable
  3. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  4. return null;
  5. }

这里 **AutowiredAnnotationBeanPostProcessor ****postProcessBeforeInstantiation()** 的方法会被调用,由于**AutowiredAnnotationBeanPostProcessor** 并没有重写这个方法,所以什么都不做。

3.1.2、findAutowiringMetadata 寻找注解元信息

操作 BeanDefinition
上面说过 postProcessBeforeInstantiation 方法返回 null 的话会继续执行doCreateBean方法:

  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  2. throws BeanCreationException {
  3. // Allow post-processors to modify the merged bean definition.
  4. synchronized (mbd.postProcessingLock) {
  5. if (!mbd.postProcessed) {
  6. try {
  7. // ************重点代码********
  8. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  9. }
  10. catch (Throwable ex) {
  11. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  12. "Post-processing of merged bean definition failed", ex);
  13. }
  14. mbd.postProcessed = true;
  15. }
  16. }
  17. ...
  18. populateBean(beanName, mbd, instanceWrapper);
  19. ...

doCreateBean 方法中,会调用调用applyMergedBeanDefinitionPostProcessors方法:

  1. protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
  2. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  3. if (bp instanceof MergedBeanDefinitionPostProcessor) {
  4. MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
  5. bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
  6. }
  7. }

MergedBeanDefinitionPostProcessor接口上面提到到的,AutowiredAnnotationBeanPostProcessor 实现了这个接口所以直接进入到AutowiredAnnotationBeanPostProcessor中的 postProcessMergedBeanDefinition方法:

  1. @Override
  2. public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  3. // 寻找需要注入的字段或方法,并封装成 InjectionMetadata
  4. // 就是利用反射遍历类的所有字段和方法,找到标注了@Resource 注解的,并缓存
  5. InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
  6. // 检查元数据中的注解信息
  7. metadata.checkConfigMembers(beanDefinition);
  8. }

InjectionMetadata 就是注入的元信息描述,主要字段如下

InjectedElement 就是注入的元素,主要字段如下:

查找注入元数据
接着继续进入到findAutowiringMetadatafindAutowiringMetadata会调用buildAutowiringMetadata方法创建注入元数据,然后将元数据缓存到injectionMetadataCache属性中:

  1. private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
  2. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
  3. // 首先从缓存中获取
  4. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  5. // 判断是否需要刷新,即metadata为null或者metadata中存储的targetClass和当前clazz不等
  6. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
  7. // 这里相当于是一个double check,防止多线程出现的并发问题
  8. synchronized (this.injectionMetadataCache) {
  9. metadata = this.injectionMetadataCache.get(cacheKey);
  10. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
  11. ...
  12. // 构建注入元信息,见下文详解
  13. metadata = buildAutowiringMetadata(clazz);
  14. // 放入缓存中
  15. this.injectionMetadataCache.put(cacheKey, metadata);
  16. }
  17. }
  18. }
  19. return metadata;
  20. }

创建需要注入的元信息AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

  1. private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
  2. // 用于判断某个类是否可能 被标记指定的某个注解
  3. if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
  4. return InjectionMetadata.EMPTY;
  5. }
  1. // 用于判断某个类是否可能 被标记指定的某个注解
  2. public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
  3. return isCandidateClass(clazz, annotationType.getName());
  4. }
  5. public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
  6. // 如果注解所在包是java开头,任何类上都可能标记这个注解
  7. // Java开头的注解包就是JDK自带的注解,任何类都可能标记.这个时候返回True就没什么问题
  8. if (annotationName.startsWith("java.")) {
  9. return true;
  10. }
  11. // 注解所在包不是java开头的情况
  12. // 可以认为是自定义注解,例如Spring的@Service @Autowired @Value 对Spring来说就是其自定义注解
  13. // 如果类的包是以java开头,则不可能标记自定义的注解
  14. if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
  15. return false;
  16. }
  17. return true;
  18. }
  19. // 这里的class就是自己的class类。如果类的包是以java开头,则不可能标记自定义的注解
  20. // 如果类的包不是以java开头
  21. static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
  22. return (type.getName().startsWith("java.") || type == Ordered.class);
  23. }