Spring源码解析-@Autowired背后发生了什么

1,103 阅读6分钟

前言

@Autowired是目前较为常用的注解,这个注解作用功能强大,可作用范围很广,那它背后做了什么,我们今天来看看

使用方式

从@Target注解可以看到,@Autowired可以作用在构造器、方法、方法参数、属性、注解上,应用在注解和方法参数上较少,在这里就不讲了

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
​
  /**
   * Declares whether the annotated dependency is required.
   * <p>Defaults to {@code true}.
   */
  boolean required() default true;
​
}
@Configuration
@ComponentScan("com.example.springdemo.life")
public class Config {
​
}
@Controller
public class AccountController implements InitializingBean {
​
    private AccountService accountService;
​
    // 作用在属性上
    @Autowired
    private UserService userService;
​
    private TokenService tokenService;
​
    public AccountController() {
        System.out.println("none");
    }
​
    // 作用在构造器上
    @Autowired
    public AccountController(AccountService accountService) {
        System.out.println("constructor accountService : " + accountService);
    }
​
    public AccountController(UserService userService) {
        System.out.println("userService");
    }
    
    // 作用在方法上
    @Autowired
    public void method(AccountService accountService) {
        System.out.println("common method accountService : " + accountService);
    }
​
    // 作用在set方法上
    @Autowired
    public void setTokenService(TokenService tokenService) {
        System.out.println("set method tokenService : " + tokenService);
        this.tokenService = tokenService;
    }
​
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("autowired field userService : " + userService);
    }
}
public class AutowiredTest {
​
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 进行包扫描
        applicationContext.register(Config.class);
        applicationContext.refresh();
​
        AccountController accountController = (AccountController) applicationContext.getBean("accountController");
        applicationContext.close();
    }
​
}

从下图的打印我们可以看到bean成功注入了,并且知道了,当@Autowired作用在方法上时,会自动调用一次方法

image.png

源码解析

从构造器上就可以看到@Autowired、@Value、@Inject都是在AutowiredAnnotationBeanPostProcessor这个类上处理的

// 注解类型
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
​
public AutowiredAnnotationBeanPostProcessor() {
    // @Autowired、@Value、@Inject在这个类上进行解析
    // 这个写法个人感觉非常好,如果想要为该类添加一个解析的注解,在这个新增即可
    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.
    }
}
  // 如果比较熟悉Spring bean生命周期中的扩展点,对这个方法应该会有点印象,这个埋点位于doCreateBean方法中
  @Override
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 收集该类相关的注解信息
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    // 对注入的meta对象进行检查,没有注册的beanDefinition需要进行注册
    metadata.checkConfigMembers(beanDefinition);
  }
​
​
​
​
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
​
    ·····
​
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
        try {
          applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        }
        catch (Throwable ex) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Post-processing of merged bean definition failed", ex);
        }
        mbd.postProcessed = true;
      }
    }
​
    ·····
  }

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // 下面的代码思路很简单,先从缓存中查看该类是否已经解析过,如果解析过不重复解析,未解析过则解析
    // 使用beanName作为缓存key,
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // 从缓存中获取数据
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    // 检查该类是否需要更新数据
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
      synchronized (this.injectionMetadataCache) {
        // 一个double check
        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;
  }
private InjectionMetadata buildAutowiringMetadata(final 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<>();
​
      // 循环类上的所有属性
      ReflectionUtils.doWithLocalFields(targetClass, field -> {
        // 查看该属性上是否有autowiredAnnotationTypes中的注解
        MergedAnnotation<?> ann = findAutowiredAnnotation(field);
        if (ann != null) {
          // @Autowired不能处理静态属性
          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));
        }
      });
​
      // 循环类上的所有方法
      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();
    }
    // 如果父类不为空且父类不是Object类
    while (targetClass != null && targetClass != Object.class);
    // 将解析过的元素封装成一个类返回
    return InjectionMetadata.forElements(elements, clazz);
  }

看看InjectionMetadata这个类,这个类封装了常用类解析后的信息

public class InjectionMetadata {
​
  // 解析的目标对象
  private final Class<?> targetClass;
  // 需要注入的对象,包括属性、方法
  private final Collection<InjectedElement> injectedElements;
  // checkConfigMembers这个方法会对injectedElements对对象进行检查,这是检查后要注入的对象
  @Nullable
  private volatile Set<InjectedElement> checkedElements;
​
​
  
  public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
    this.targetClass = targetClass;
    this.injectedElements = elements;
  }
​
​
  
  protected boolean needsRefresh(Class<?> clazz) {
    return this.targetClass != clazz;
  }
​
  public void checkConfigMembers(RootBeanDefinition beanDefinition) {
    Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
    for (InjectedElement element : this.injectedElements) {
      Member member = element.getMember();
      if (!beanDefinition.isExternallyManagedConfigMember(member)) {
        beanDefinition.registerExternallyManagedConfigMember(member);
        checkedElements.add(element);
        if (logger.isTraceEnabled()) {
          logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
        }
      }
    }
    this.checkedElements = checkedElements;
  }
  // 对对象进行注入
  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);
      }
    }
  }
​
​
  // buildAutowiringMetadata中使用过这个方法,把解析后对象的数据封装成InjectionMetadata
  public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
    return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
  }
​
  // 这个方法上面有使用过,应该很熟悉
  public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Class<?> clazz) {
    return (metadata == null || metadata.needsRefresh(clazz));
  }
​
​
​
  public abstract static class InjectedElement {
    // 这个类是method和field的父类
    protected final Member member;
    // 区分field还是method
    protected final boolean isField;
    // method时会使用到这个对象,因为可能不止一个属性
    @Nullable
    protected final PropertyDescriptor pd;
​
    @Nullable
    protected volatile Boolean skip;
​
    protected InjectedElement(Member member, @Nullable PropertyDescriptor pd) {
      this.member = member;
      this.isField = (member instanceof Field);
      this.pd = pd;
    }
​
  }
}
@Override
  public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
      // 对metadata中的属性进行注入,里面用了反射的技术
      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

看了以上的代码之后,我们来手写一个简易版的@Autowired,就当小作业了

首先定义一个MyAutowired的注解,因为是简易版,所以我们定义它只能在属性上使用

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
}

仿照AutowiredAnnotationBeanPostProcessor写了个处理MyAutowired注解的BeanPostProcessor,代码基本都是照搬的

// 类上加Component这个BeanPostProcessor就会注册到ioc容器中,至于为什么,大家可以看我之前的文章
@Component
public class MyAutowiredAnnotationBeanPostProcessor implements MergedBeanDefinitionPostProcessor,
        InstantiationAwareBeanPostProcessor, BeanFactoryAware {
​
    private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
​
    private final Map<String, InjectionMetadata> myInjectionMetadataCache = new ConcurrentHashMap<>(256);
​
​
    @Nullable
    private ConfigurableListableBeanFactory beanFactory;
​
    public MyAutowiredAnnotationBeanPostProcessor() {
        // 只处理MyAutowired注解
        this.autowiredAnnotationTypes.add(MyAutowired.class);
    }
​
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }
​
​
    @SneakyThrows
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        metadata.inject(bean, beanName, pvs);
        return pvs;
    }
​
​
    private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
        InjectionMetadata metadata = this.myInjectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized (this.myInjectionMetadataCache) {
                metadata = this.myInjectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
                    metadata = buildAutowiringMetadata(clazz);
                    this.myInjectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }
​
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }
​
​
    private class MyAutowiredFieldElement extends InjectionMetadata.InjectedElement {
​
        public MyAutowiredFieldElement(Field field) {
            super(field, null);
        }
​
        // 在写的时候没想到inject方式可以自定义,这个在看源码的时候很难察觉,自己手写对源码理解还是很大的
        @Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            DependencyDescriptor desc = new DependencyDescriptor(field, false);
            desc.setContainingClass(bean.getClass());
            Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
            Assert.state(beanFactory != null, "No BeanFactory available");
            TypeConverter typeConverter = beanFactory.getTypeConverter();
​
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
​
            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }
        }
​
    }
    
    // 我们只处理属性,删除了处理方法的代码
    private InjectionMetadata buildAutowiringMetadata(final 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<>();
​
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                MergedAnnotation<?> ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        return;
                    }
                    currElements.add(new MyAutowiredFieldElement(field));
                }
            });
​
            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);
​
        return InjectionMetadata.forElements(elements, clazz);
    }
​
​
    @Nullable
    private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
        MergedAnnotations annotations = MergedAnnotations.from(ao);
        for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
            MergedAnnotation<?> annotation = annotations.get(type);
            if (annotation.isPresent()) {
                return annotation;
            }
        }
        return null;
    }
}
​

做一下测试

@Controller
public class UserController {
​
    @MyAutowired
    private AccountService accountService;
​
    @MyAutowired
    private UserService userService;
​
    public void myMethod() {
        System.out.println("method accountService : " + accountService);
        System.out.println("method userService : " + userService);
    }
}
public class MyAutowiredTest {
​
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(Config.class);
        applicationContext.refresh();
​
        UserController userController = (UserController) applicationContext.getBean("userController");
        userController.myMethod();
        applicationContext.close();
    }
}

image.png

总结

使用@Autowired实现注入是通过AutowiredAnnotationBeanPostProcessor这个类来实现的,基本思路是在Spring bean生命周期扩展点的基础上,使用postProcessMergedBeanDefinition这个方法实现类信息的解析,再在postProcessProperties这个扩展点实现类属性的注入

@Resource的处理方式跟@Autowired是如出一辙的,处理类是CommonAnnotationBeanPostProcessor,大家有兴趣可以去看看这个类的代码

Spring官方推荐使用构造器注入的方式来实现属性的注入,@Autowired不太建议,因为使用@Autowired屏蔽了类的循环依赖问题,项目中出现循环依赖说明项目中的领域与领域之间的调用关系模糊不清,可维护性不佳,使用构造器注入可以暴露出这个问题