AI智能
改变未来

死磕Spring之IoC篇 – @Autowired 等注解的实现原理

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读

Spring 版本:5.1.14.RELEASE

开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》这一篇文章

该系列其他文章请查看:《死磕 Spring 之 IoC 篇 – 文章导读》

@Autowired 等注解的实现原理

在上一篇《Bean 的属性填充阶段》文章中讲到,在创建一个 Bean 的实例对象后,会对这个 Bean 进行属性填充。在属性填充的过程中,获取到已定义的属性值,然后会通过 InstantiationAwareBeanPostProcessor 对该属性值进行处理,最后通过反射机制将属性值设置到这个 Bean 中。在 Spring 内部有以下两个 InstantiationAwareBeanPostProcessor 处理器:

  • AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
  • CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值

本文将会分析这两个处理器的实现,以及涉及到的相关对象

这两个处理器在哪被注册?

在前面的《解析自定义标签(XML 文件)》《BeanDefinition 的解析过程(面向注解)》文章中可以知道,在 XML 文件中的

<context:component-scan />

标签的处理过程中,会底层借助于

ClassPathBeanDefinitionScanner

扫描器,去扫描指定路径下符合条件(@Component 注解)的 BeanDefinition 们,关于 @ComponentScan 注解的解析也是借助于这个扫描器实现的。扫描过程如下:

// ClassPathBeanDefinitionScanner.javapublic int scan(String... basePackages) {// <1> 获取扫描前的 BeanDefinition 数量int beanCountAtScanStart = this.registry.getBeanDefinitionCount();// <2> 进行扫描,将过滤出来的所有的 .class 文件生成对应的 BeanDefinition 并注册doScan(basePackages);// Register annotation config processors, if necessary.// <3> 如果 `includeAnnotationConfig` 为 `true`(默认),则注册几个关于注解的 PostProcessor 处理器(关键)// 在其他地方也会注册,内部会进行判断,已注册的处理器不会再注册if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}// <4> 返回本次扫描注册的 BeanDefinition 数量return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);}

在第

<3>

步会调用 AnnotationConfigUtils 的

registerAnnotationConfigProcessors(BeanDefinitionRegistry)

方法,如下:

// AnnotationConfigUtils.javapublic static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);}/*** Register all relevant annotation post processors in the given registry.* @param registry the registry to operate on* @param source the configuration source element (already extracted)* that this registration was triggered from. May be {@code null}.* @return a Set of BeanDefinitionHolders, containing all bean definitions* that have actually been registered by this call*/public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);// 处理 Spring 应用上下文中的配置类if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}// 处理 @Autowired 以及 @Value 注解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));}// (条件激活)处理 JSR-250 注解 @Resource,如 @PostConstruct、@PreDestroy 等// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// Processor 对象(条件激活)处理 JPA 注解场景// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}// 处理标注 @EventListener 的 Spring 事件监听方法if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}// 用于 @EventListener 标注的事件监听方法构建成 ApplicationListener 对象if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

在这个方法中可以看到会注册 AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor 两个处理器,然后在 Spring 应用上下文刷新阶段会将其初始化并添加至 AbstractBeanFactory 的

beanPostProcessors

集合中,那么接下来我们先来分析这两个处理器

回顾 Bean 的创建过程

第一步:回到《Bean 的创建过程》文章中的“对 RootBeanDefinition 加工处理”小节,会调用这个方法:

// AbstractAutowireCapableBeanFactory.javaprotected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof MergedBeanDefinitionPostProcessor) {MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}}

调用所有 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法对 RootBeanDefinition 进行加工处理,例如:

  • AutowiredAnnotationBeanPostProcessor,会先解析出
    @Autowired

    @Value

    注解标注的属性的注入元信息,后续进行依赖注入

  • CommonAnnotationBeanPostProcessor,会先解析出
    @Resource

    注解标注的属性的注入元信息,后续进行依赖注入,它也会找到

    @PostConstruct

    @PreDestroy

    注解标注的方法,并构建一个 LifecycleMetadata 对象,用于后续生命周期中的初始化和销毁

第二步:回到《Bean 的创建过程》文章中的“属性填充”小节,该过程会进行下面的处理:

// <5> 通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对 `pvs` 进行处理if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}// <5.1> 遍历所有的 BeanPostProcessorfor (BeanPostProcessor bp : getBeanPostProcessors()) {// 如果为 InstantiationAwareBeanPostProcessor 类型if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// <5.2> 调用处理器的 `postProcessProperties(...)` 方法,对 `pvs` 进行后置处理PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);// <5.3> 如果上一步的处理结果为空,可能是新版本导致的(Spring 5.1 之前没有上面这个方法),则需要兼容老版本if (pvsToUse == null) {// <5.3.1> 找到这个 Bean 的所有 `java.beans.PropertyDescriptor` 属性描述器(包含这个属性的所有信息)if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}// <5.3.2> 调用处理器的 `postProcessPropertyValues(...)` 方法,对 `pvs` 进行后置处理pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);// <5.3.3> 如果处理后的 PropertyValues 对象为空,直接 `return`,则不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充if (pvsToUse == null) {return;}}// <5.4> 将处理后的 `pvsToUse` 复制给 `pvs`pvs = pvsToUse;}}}

这里不会调用所有 InstantiationAwareBeanPostProcessor 的 postProcessProperties 方法对

pvs

(MutablePropertyValues)属性值对象进行处理,例如:

  • AutowiredAnnotationBeanPostProcessor,会根据前面解析出来的
    @Autowired

    @Value

    注解标注的属性的注入元信息,进行依赖注入

  • CommonAnnotationBeanPostProcessor,会根据前面解析出来的
    @Resource

    注解标注的属性的注入元信息,进行依赖注入

可以看到

@Autowired

@Value

@Resource

注解的实现就是基于这两个处理器实现的,接下来我们来看看这两个处理器的具体实现

AutowiredAnnotationBeanPostProcessor

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

,主要处理

@Autowired

@Value

注解进行依赖注入

体系结构

可以看到 AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 两个接口

构造方法

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapterimplements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {/*** 保存需要处理的注解*/private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);private String requiredParameterName = "required";private boolean requiredParameterValue = true;private int order = Ordered.LOWEST_PRECEDENCE - 2;@Nullableprivate ConfigurableListableBeanFactory beanFactory;private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);/*** 缓存需要注入的字段元信息*/private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);/*** Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring\'s* standard {@link Autowired @Autowired} annotation.* <p>Also supports JSR-330\'s {@link javax.inject.Inject @Inject} annotation,* if available.*/@SuppressWarnings("unchecked")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.}}}

可以看到会添加

@Autowired

@Value

两个注解,如果存在 JSR-330 的

javax.inject.Inject

注解,也是支持的

postProcessMergedBeanDefinition 方法

postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)

方法,找到

@Autowired

@Value

注解标注的字段(或方法)的元信息,如下:

@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {// 找到这个 Bean 所有需要注入的属性(@Autowired 或者 @Value 注解)InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}

直接调用

findAutowiringMetadata(...)

方法获取这个 Bean 的注入元信息对象

1. findAutowiringMetadata 方法
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {// Fall back to class name as cache key, for backwards compatibility with custom callers.// 生成一个缓存 KeyString cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());// Quick check on the concurrent map first, with minimal locking.// 先尝试从缓存中获取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;}

首先尝试从缓存中获取这个 Bean 对应的注入元信息对象,没有找到的话则调用

buildAutowiringMetadata(final Class<?> clazz)

构建一个,然后再放入缓存中

2. buildAutowiringMetadata 方法
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {// <1> 创建 `currElements` 集合,用于保存 @Autowired、@Value 注解标注的字段final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();// <2> 遍历这个 Class 对象的所有字段ReflectionUtils.doWithLocalFields(targetClass, field -> {// <2.1> 找到该字段的 @Autowired 或者 @Value 注解,返回 `ann` 对象,没有的话返回空对象,则直接跳过不进行下面的操作AnnotationAttributes ann = findAutowiredAnnotation(field);if (ann != null) {// <2.2> 进行过滤,static 修饰的字段不进行注入if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;}// <2.3> 获取注解中的 `required` 配置boolean required = determineRequiredStatus(ann);// <2.4> 根据该字段和 `required` 构建一个 AutowiredFieldElement 对象,添加至 `currElements`currElements.add(new AutowiredFieldElement(field, required));}});// <3> 遍历这个 Class 对象的所有方法ReflectionUtils.doWithLocalMethods(targetClass, method -> {// <3.1> 尝试找到这个方法的桥接方法,没有的话就是本身这个方法Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);// <3.2> 如果是桥接方法则直接跳过if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}// <3.3> 找到该方法的 @Autowired 或者 @Value 注解,返回 `ann` 对象,没有的话返回空对象,则直接跳过不进行下面的操作AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {// <3.4> 进行过滤,static 修饰的方法不进行注入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);}}// <3.5> 获取注解中的 `required` 配置boolean required = determineRequiredStatus(ann);PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);// <3.6> 构建一个 AutowiredMethodElement 对象,添加至 `currElements`currElements.add(new AutowiredMethodElement(method, required, pd));}});elements.addAll(0, currElements);// <4> 找到父类,循环遍历targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);// <5> 根据从这个 Bean 解析出来的所有 InjectedElement 对象生成一个 InjectionMetadata 注入元信息对象,并返回return new InjectionMetadata(clazz, elements);}

过程如下:

  1. 创建
    currElements

    集合,用于保存

    @Autowired

    @Value

    注解标注的字段

  2. 遍历这个 Class 对象的所有字段找到该字段的
    @Autowired

    或者

    @Value

    注解,返回

    ann

    对象,没有的话返回空对象,则直接跳过不进行下面的操作

  3. 进行过滤,static 修饰的字段不进行注入
  4. 获取注解中的
    required

    配置

  5. 根据该字段和
    required

    构建一个 AutowiredFieldElement 对象,添加至

    currElements
  • 遍历这个 Class 对象的所有方法
      尝试找到这个方法的桥接方法,没有的话就是本身这个方法
    1. 如果是桥接方法则直接跳过
    2. 找到该方法的
      @Autowired

      或者

      @Value

      注解,返回

      ann

      对象,没有的话返回空对象,则直接跳过不进行下面的操作

    3. 进行过滤,static 修饰的方法不进行注入
    4. 获取注解中的
      required

      配置

    5. 构建一个 AutowiredMethodElement 对象,添加至
      currElements
  • 找到父类,循环遍历
  • 根据从这个 Bean 解析出来的所有 InjectedElement 对象生成一个 InjectionMetadata 注入元信息对象,并返回
  • 整个过程很简单,就是解析出所有

    @Autowired

    或者

    @Value

    注解标注的方法或者字段,然后构建一个 InjectionMetadata 注入元信息对象

    postProcessProperties 方法

    postProcessProperties(PropertyValues pvs, Object bean, String beanName)

    方法,根据

    @Autowired

    @Value

    注解标注的字段(或方法)的元信息进行依赖注入,如下:

    @Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 找到这个 Bean 的注入元信息对象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;}

    先找到这个 Bean 的注入元信息对象,上面已经讲过了,然后调用其

    inject(...)

    方法,这里先来看到

    InjectionMetadata

    这个对象

    InjectionMetadata 注入元信息对象

    org.springframework.beans.factory.annotation.InjectionMetadata

    ,某个 Bean 的注入元信息对象

    public class InjectionMetadata {private static final Log logger = LogFactory.getLog(InjectionMetadata.class);private final Class<?> targetClass;/*** 需要注入的字段(或方法)的元信息*/private final Collection<InjectedElement> injectedElements;@Nullableprivate volatile Set<InjectedElement> checkedElements;public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {this.targetClass = targetClass;this.injectedElements = elements;}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);}}}}

    可以看到注入方法非常简单,就是遍历所有的 InjectedElement 对象,调用他们的

    inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)

    方法

    AutowiredFieldElement

    AutowiredAnnotationBeanPostProcessor 的私有内部类,注入字段对象,如下:

    private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {/** 是否必须 */private final boolean required;/** 是否缓存起来了 */private volatile boolean cached = false;/** 缓存的对象 */@Nullableprivate volatile Object cachedFieldValue;public AutowiredFieldElement(Field field, boolean required) {super(field, null);this.required = required;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// <1> 获取 `field` 字段Field field = (Field) this.member;Object value;// <2> 如果进行缓存了,则尝试从缓存中获取if (this.cached) {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}// <3> 否则,开始进行解析else {// <3.1> 创建一个依赖注入描述器 `desc`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 {/*** <3.2> 通过 {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency} 方法* 找到这个字段对应的 Bean(们)*/value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}// <3.3> 和缓存相关,如果有必要则将本次找到的注入对象缓存起来,避免下次再进行解析synchronized (this) {if (!this.cached) {if (value != null || this.required) {this.cachedFieldValue = desc;registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}else {this.cachedFieldValue = null;}this.cached = true;}}}// <4> 如果获取到该字段对应的对象,则进行属性赋值(依赖注入)if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}}

    直接看到

    inject(...)

    方法,注入的过程如下:

    1. 获取
      field

      字段

    2. 如果进行缓存了,则尝试从缓存中获取
    3. 否则,开始进行解析创建一个依赖注入描述器
      desc
    4. **【核心】**通过
      DefaultListableBeanFactory#resolveDependency(...)

      方法,找到这个字段对应的 Bean(们)

    5. 和缓存相关,如果有必要则将本次找到的注入对象缓存起来,避免下次再进行解析
  • 如果获取到该字段对应的对象,则进行属性赋值(依赖注入),底层就是通过反射机制为该字段赋值
  • 可以看到整个的核心在于通过

    DefaultListableBeanFactory#resolveDependency(...)

    方法找到字段对应的 Bean,这里也许是一个集合对象,所以也可能找到的是多个 Bean,该方法在后面进行分析

    AutowiredMethodElement

    AutowiredAnnotationBeanPostProcessor 的私有内部类,注入方法对象,如下:

    private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {/** 是否必须 */private final boolean required;/** 是否缓存起来了 */private volatile boolean cached = false;/** 缓存的方法参数对象 */@Nullableprivate volatile Object[] cachedMethodArguments;public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {super(method, pd);this.required = required;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {if (checkPropertySkipping(pvs)) {return;}// <1> 获取 `method` 方法Method method = (Method) this.member;// <2> 如果进行缓存了,则尝试从缓存中获取方法参数对象Object[] arguments;if (this.cached) {// Shortcut for avoiding synchronization...arguments = resolveCachedArguments(beanName);}// <3> 否则,开始进行解析else {// <3.1> 获取方法的参数类型集合 `paramTypes`,根据参数位置确定参数Class<?>[] paramTypes = method.getParameterTypes();arguments = new Object[paramTypes.length];// <3.2> 构建一个依赖注入描述器数组 `descriptors`,用于保存后续创建的对象DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();// <3.3> 根据参数顺序遍历该方法的参数for (int i = 0; i < arguments.length; i++) {// <3.3.1> 为第 `i` 个方法参数创建一个 MethodParameter 对象MethodParameter methodParam = new MethodParameter(method, i);// <3.3.2> 创建依赖描述器 `currDesc`,并添加至 `descriptors` 数组DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);currDesc.setContainingClass(bean.getClass());descriptors[i] = currDesc;try {/*** <3.3.3> 通过 {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency} 方法* 找到这个方法参数对应的 Bean(们)*/Object 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);}}// <3.4> 和缓存相关,如果有必要则将本次找到的方法参数对象缓存起来,避免下次再进行解析synchronized (this) {if (!this.cached) {if (arguments != null) {Object[] cachedMethodArguments = new Object[paramTypes.length];System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length);registerDependentBeans(beanName, autowiredBeans);if (autowiredBeans.size() == paramTypes.length) {Iterator<String> it = autowiredBeans.iterator();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;}}}// <4> 如果找到该方法的参数(们),则进行属性赋值(依赖注入)if (arguments != null) {try {ReflectionUtils.makeAccessible(method);// 通过反射机制调用该方法method.invoke(bean, arguments);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}}

    直接看到

    inject(...)

    方法,注入的过程如下:

    1. 获取
      method

      方法

    2. 如果进行缓存了,则尝试从缓存中获取方法参数对象
    3. 否则,开始进行解析获取方法的参数类型集合
      paramTypes

      ,根据参数位置确定参数

    4. 构建一个依赖注入描述器数组
      descriptors

      ,用于保存后续创建的对象

    5. 根据参数顺序遍历该方法的参数为第
      i

      个方法参数创建一个 MethodParameter 对象

    6. 创建依赖描述器
      currDesc

      ,并添加至

      descriptors

      数组

    7. **【核心】**通过
      DefaultListableBeanFactory#resolveDependency(...)

      方法,找到这个方法参数对应的 Bean(们)

    8. 和缓存相关,如果有必要则将本次找到的方法参数对象缓存起来,避免下次再进行解析
  • 如果找到该方法的参数(们),则进行属性赋值(依赖注入),底层就是通过反射机制调用该方法
  • 可以看到整个的核心也是通过

    DefaultListableBeanFactory#resolveDependency(...)

    方法找到方法参数对应的 Bean,该方法在后面进行分析

    CommonAnnotationBeanPostProcessor

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

    ,主要处理

    @Resource

    注解进行依赖注入,以及

    @PostConstruct

    @PreDestroy

    生命周期注解的处理

    体系结构

    可以看到 CommonAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 两个接口,还实现了 DestructionAwareBeanPostProcessor 接口,用于生命周期中的初始化和销毁的处理

    构造方法

    public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessorimplements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {@Nullableprivate static Class<? extends Annotation> webServiceRefClass;@Nullableprivate static Class<? extends Annotation> ejbRefClass;static {try {@SuppressWarnings("unchecked")Class<? extends Annotation> clazz = (Class<? extends Annotation>)ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());webServiceRefClass = clazz;}catch (ClassNotFoundException ex) {webServiceRefClass = null;}try {@SuppressWarnings("unchecked")Class<? extends Annotation> clazz = (Class<? extends Annotation>)ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());ejbRefClass = clazz;}catch (ClassNotFoundException ex) {ejbRefClass = null;}}/*** Create a new CommonAnnotationBeanPostProcessor,* with the init and destroy annotation types set to* {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy},* respectively.*/public CommonAnnotationBeanPostProcessor() {setOrder(Ordered.LOWEST_PRECEDENCE - 3);setInitAnnotationType(PostConstruct.class);setDestroyAnnotationType(PreDestroy.class);ignoreResourceType("javax.xml.ws.WebServiceContext");}}public class InitDestroyAnnotationBeanPostProcessorimplements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {protected transient Log logger = LogFactory.getLog(getClass());/*** 初始化注解,默认为 @PostConstruct*/@Nullableprivate Class<? extends Annotation> initAnnotationType;/*** 销毁注解,默认为 @PreDestroy*/@Nullableprivate Class<? extends Annotation> destroyAnnotationType;private int order = Ordered.LOWEST_PRECEDENCE;@Nullableprivate final transient Map<Class<?>, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {this.initAnnotationType = initAnnotationType;}public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {this.destroyAnnotationType = destroyAnnotationType;}}

    可以看到会设置初始化注解为

    @PostConstruct

    ,销毁注解为

    @PreDestroy

    ,这两个注解都是 JSR-250 注解;另外如果存在

    javax.xml.ws.WebServiceRef

    javax.ejb.EJB

    注解也是会进行设置的

    postProcessMergedBeanDefinition 方法

    postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)

    方法,找到

    @PostConstruct

    @PreDestroy

    注解标注的方法,并构建 LifecycleMetadata 对象,找到

    @Resource

    注解标注的字段(或方法)的元信息,如下:

    // CommonAnnotationBeanPostProcessor.java@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {// 先调用父类的方法,找到 @PostConstruct 和 @PreDestroy 注解标注的方法,并构建 LifecycleMetadata 对象super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);// 找到 @Resource 注解标注的字段(或方法),构建一个 InjectionMetadata 对象,用于后续的属性注入InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}

    整个的过程原理和 AutowiredAnnotationBeanPostProcessor 差不多,先从缓存中获取,未命中则调用对应的方法进行构建,下面先来看看父类中的方法

    buildLifecycleMetadata 方法
    // InitDestroyAnnotationBeanPostProcessor.javaprivate LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {List<LifecycleElement> initMethods = new ArrayList<>();List<LifecycleElement> destroyMethods = new ArrayList<>();Class<?> targetClass = clazz;do {final List<LifecycleElement> currInitMethods = new ArrayList<>();final List<LifecycleElement> currDestroyMethods = new ArrayList<>();ReflectionUtils.doWithLocalMethods(targetClass, method -> {if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {LifecycleElement element = new LifecycleElement(method);currInitMethods.add(element);if (logger.isTraceEnabled()) {logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);}}if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {currDestroyMethods.add(new LifecycleElement(method));if (logger.isTraceEnabled()) {logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);}}});initMethods.addAll(0, currInitMethods);destroyMethods.addAll(currDestroyMethods);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return new LifecycleMetadata(clazz, initMethods, destroyMethods);}

    整个过程比较简单,找到这个 Bean 中

    @PostConstruct

    @PreDestroy

    注解标注的方法,然后构建一个 LifecycleMetadata 生命周期元信息对象

    buildResourceMetadata 方法
    // CommonAnnotationBeanPostProcessor.javaprivate InjectionMetadata buildResourceMetadata(final Class<?> clazz) {List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();ReflectionUtils.doWithLocalFields(targetClass, field -> {if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");}currElements.add(new WebServiceRefElement(field, field, null));}else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@EJB annotation is not supported on static fields");}currElements.add(new EjbRefElement(field, field, null));}else if (field.isAnnotationPresent(Resource.class)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static fields");}if (!this.ignoredResourceTypes.contains(field.getType().getName())) {currElements.add(new ResourceElement(field, field, null));}}});ReflectionUtils.doWithLocalMethods(targetClass, method -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");}if (method.getParameterCount() != 1) {throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);}PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));}else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@EJB annotation is not supported on static methods");}if (method.getParameterCount() != 1) {throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);}PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new EjbRefElement(method, bridgedMethod, pd));}else if (bridgedMethod.isAnnotationPresent(Resource.class)) {if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static methods");}Class<?>[] paramTypes = method.getParameterTypes();if (paramTypes.length != 1) {throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);}if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new ResourceElement(method, bridgedMethod, pd));}}}});elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return new InjectionMetadata(clazz, elements);}

    整个过程也比较简单,解析出这个 Bean 带有

    @Resource

    注解的所有字段(或方法),构建成对应的 ResourceElement 对象,然后再构建成一个 InjectionMetadata 注入元信息对象

    postProcessProperties 方法

    postProcessProperties(PropertyValues pvs, Object bean, String beanName)

    方法,根据

    @Resource

    注解标注的字段(或方法)的元信息进行依赖注入,如下:

    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);try {// 进行注入metadata.inject(bean, beanName, pvs);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);}return pvs;}

    先找到这个 Bean 的注入元信息对象,上面已经讲过了,然后调用其

    inject(...)

    方法,该对象上面已经讲过了,实际就是调用其内部 InjectedElement 的

    inject(...)

    方法

    postProcessBeforeInitialization 方法

    初始化 Bean 的时候会先执行

    @PostConstruct

    标注的初始化方法

    // InitDestroyAnnotationBeanPostProcessor.java@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 找到 @PostConstruct 和 @PreDestroy 注解标注的方法们所对应的 LifecycleMetadata 对象LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {// 执行 @PostConstruct 标注的初始化方法metadata.invokeInitMethods(bean, beanName);}catch (InvocationTargetException ex) {throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());}catch (Throwable ex) {throw new BeanCreationException(beanName, "Failed to invoke init method", ex);}return bean;}// InitDestroyAnnotationBeanPostProcessor.LifecycleMetadatapublic void invokeInitMethods(Object target, String beanName) throws Throwable {Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;Collection<LifecycleElement> initMethodsToIterate =(checkedInitMethods != null ? checkedInitMethods : this.initMethods);if (!initMethodsToIterate.isEmpty()) {for (LifecycleElement element : initMethodsToIterate) {if (logger.isTraceEnabled()) {logger.trace("Invoking init method on bean \'" + beanName + "\': " + element.getMethod());}element.invoke(target);}}}

    postProcessBeforeDestruction 方法

    销毁 Bean 的时候先执行

    @PreDestroy

    注解标注的销毁方法

    // InitDestroyAnnotationBeanPostProcessor.java@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {// 找到 @PostConstruct 和 @PreDestroy 注解标注的方法们所对应的 LifecycleMetadata 对象LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {// 执行 @PreDestroy 标注的销毁方法metadata.invokeDestroyMethods(bean, beanName);}catch (InvocationTargetException ex) {String msg = "Destroy method on bean with name \'" + beanName + "\' threw an exception";if (logger.isDebugEnabled()) {logger.warn(msg, ex.getTargetException());}else {logger.warn(msg + ": " + ex.getTargetException());}}catch (Throwable ex) {logger.warn("Failed to invoke destroy method on bean with name \'" + beanName + "\'", ex);}}// InitDestroyAnnotationBeanPostProcessor.LifecycleMetadatapublic void invokeDestroyMethods(Object target, String beanName) throws Throwable {Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;Collection<LifecycleElement> destroyMethodsToUse =(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);if (!destroyMethodsToUse.isEmpty()) {for (LifecycleElement element : destroyMethodsToUse) {if (logger.isTraceEnabled()) {logger.trace("Invoking destroy method on bean \'" + beanName + "\': " + element.getMethod());}element.invoke(target);}}}

    ResourceElement

    CommonAnnotationBeanPostProcessor 的私有内部类,@Resource 注入字段(或方法)对象

    构造方法

    protected abstract class LookupElement extends InjectionMetadata.InjectedElement {/** Bean 的名称 */protected String name = "";/** 是否为默认的名称(通过注解定义的) */protected boolean isDefaultName = false;/** Bean 的类型 */protected Class<?> lookupType = Object.class;@Nullableprotected String mappedName;public LookupElement(Member member, @Nullable PropertyDescriptor pd) {super(member, pd);}public final DependencyDescriptor getDependencyDescriptor() {if (this.isField) {return new LookupDependencyDescriptor((Field) this.member, this.lookupType);}else {return new LookupDependencyDescriptor((Method) this.member, this.lookupType);}}}private class ResourceElement extends LookupElement {/** 是否延迟加载 */private final boolean lazyLookup;public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {super(member, pd);Resource resource = ae.getAnnotation(Resource.class);String resourceName = resource.name();Class<?> resourceType = resource.type();this.isDefaultName = !StringUtils.hasLength(resourceName);if (this.isDefaultName) {resourceName = this.member.getName();if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {resourceName = Introspector.decapitalize(resourceName.substring(3));}}else if (embeddedValueResolver != null) {resourceName = embeddedValueResolver.resolveStringValue(resourceName);}if (Object.class != resourceType) {checkResourceType(resourceType);}else {// No resource type specified... check field/method.resourceType = getResourceType();}this.name = (resourceName != null ? resourceName : "");this.lookupType = resourceType;String lookupValue = resource.lookup();this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());Lazy lazy = ae.getAnnotation(Lazy.class);this.lazyLookup = (lazy != null && lazy.value());}}

    ResourceElement 的构造方法会通过

    @Resource

    注解和该字段(或方法)解析出基本信息

    可以看到还继承了 InjectionMetadata 的静态内部类 InjectedElement,我们先来看到这个类的

    inject(...)

    方法

    inject 方法

    public abstract static class InjectedElement {protected final Member member;protected final boolean isField;protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)throws Throwable {if (this.isField) {Field field = (Field) this.member;ReflectionUtils.makeAccessible(field);field.set(target, getResourceToInject(target, requestingBeanName));} else {if (checkPropertySkipping(pvs)) {return;}try {Method method = (Method) this.member;ReflectionUtils.makeAccessible(method);method.invoke(target, getResourceToInject(target, requestingBeanName));}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}@Nullableprotected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {return null;}}

    不管是字段还是方法,底层都是通过反射机制进行赋值或者调用,都会调用

    getResourceToInject(...)

    方法获取到字段值或者方法参数

    getResourceToInject 方法

    @Overrideprotected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :getResource(this, requestingBeanName));}

    如果是延迟加载,则调用

    buildLazyResourceProxy(...)

    方法返回一个代理对象,如下:

    protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return element.lookupType;}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {return getResource(element, requestingBeanName);}@Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf = new ProxyFactory();pf.setTargetSource(ts);if (element.lookupType.isInterface()) {pf.addInterface(element.lookupType);}ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null);return pf.getProxy(classLoader);}

    否则,调用

    getResource(...)

    方法获取注入对象

    getResource 方法

    protected Object getResource(LookupElement element, @Nullable String requestingBeanName)throws NoSuchBeanDefinitionException {if (StringUtils.hasLength(element.mappedName)) {return this.jndiFactory.getBean(element.mappedName, element.lookupType);}if (this.alwaysUseJndiLookup) {return this.jndiFactory.getBean(element.name, element.lookupType);}if (this.resourceFactory == null) {throw new NoSuchBeanDefinitionException(element.lookupType,"No resource factory configured - specify the \'resourceFactory\' property");}return autowireResource(this.resourceFactory, element, requestingBeanName);}

    前面的判断忽略掉,直接看到最后会调用

    autowireResource(...)

    方法,并返回注入信息

    autowireResource 方法

    protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)throws NoSuchBeanDefinitionException {Object resource;Set<String> autowiredBeanNames;String name = element.name;if (factory instanceof AutowireCapableBeanFactory) {AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;DependencyDescriptor descriptor = element.getDependencyDescriptor();if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {autowiredBeanNames = new LinkedHashSet<>();resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);if (resource == null) {throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");}}else {resource = beanFactory.resolveBeanByName(name, descriptor);autowiredBeanNames = Collections.singleton(name);}}else {resource = factory.getBean(name, element.lookupType);autowiredBeanNames = Collections.singleton(name);}if (factory instanceof ConfigurableBeanFactory) {ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;for (String autowiredBeanName : autowiredBeanNames) {if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);}}}return resource;}

    @Resource

    注解相比于

    @Autowired

    注解的处理更加复杂点,不过我们这里可以看到也会调用

    DefaultListableBeanFactory#resolveDependency(...)

    方法,找到对应的注入对象,该方法在后面进行分析

    1. resolveDependency 处理依赖方法

    resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter)

    方法,找到对应的依赖 Bean,该方法在《Bean 的创建过程》中也提到了,获取 Bean 的实例对象时,构造器注入的参数也是通过该方法获取的,本文的依赖注入底层也是通过该方法实现的,这里我们对该方法一探究竟

    // DefaultListableBeanFactory.java@Override@Nullablepublic Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// <1> 设置参数名称探测器,例如通过它获取方法参数的名称descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());// <2> 如果依赖类型为 Optional 类型if (Optional.class == descriptor.getDependencyType()) {// 调用 `createOptionalDependency(...)` 方法,先将 `descriptor` 注入表述器封装成 NestedDependencyDescriptor 对象// 底层处理和下面的 `5.2` 相同return createOptionalDependency(descriptor, requestingBeanName);}// <3> 否则,如果依赖类型为 ObjectFactory 或 ObjectProvider 类型else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) {// 返回一个 DependencyObjectProvider 私有内部类对象,并没有获取到实例的 Bean,需要调用其 getObject() 方法获取目标对象return new DependencyObjectProvider(descriptor, requestingBeanName);}// <4> 否则,如果依赖类型为 javax.inject.Provider 类型else if (javaxInjectProviderClass == descriptor.getDependencyType()) {// 返回一个 Jsr330Provider 私有内部类对象,该对象也继承 DependencyObjectProviderreturn new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}// <5> 否则,通用的处理逻辑else {// <5.1> 先通过 AutowireCandidateResolver 尝试获取一个代理对象,延迟依赖注入则会返回一个代理对象Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);// <5.2> 如果上面没有返回代理对象,则进行处理,调用 `doResolveDependency(...)` 方法if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}

    过程如下:

    1. 设置参数名称探测器,例如通过它获取方法参数的名称
    2. 如果依赖类型为 Optional 类型,则调用
      createOptionalDependency(...)

      方法,先将

      descriptor

      注入表述器封装成 NestedDependencyDescriptor 对象,底层处理和下面的

      5.2

      相同

    3. 否则,如果依赖类型为 ObjectFactory 或 ObjectProvider 类型,直接返回一个
      DependencyObjectProvider

      私有内部类对象,并没有获取到实例的 Bean,需要调用其 getObject() 方法获取目标对象

    4. 否则,如果依赖类型为 javax.inject.Provider 类型,直接返回一个
      Jsr330Provider

      私有内部类对象,该对象也继承 DependencyObjectProvider

    5. 否则,通用的处理逻辑先通过 AutowireCandidateResolver 尝试获取一个代理对象,延迟依赖注入则会返回一个代理对象
    6. 如果上面没有返回代理对象,则进行处理,调用
      doResolveDependency(...)

      方法

    我们需要关注的是上面的第

    5.2

    步所调用

    doResolveDependency(...)

    方法,这一步是底层实现

    2. doResolveDependency 底层处理依赖方法

    // DefaultListableBeanFactory.java@Nullablepublic Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// 设置当前线程的注入点,并返回上次的注入点,属于嵌套注入的一个保护点InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {// <1> 针对给定的工厂给定一个快捷实现的方式,暂时忽略// 例如考虑一些预先解析的信息,在进入所有 Bean 的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {// 返回快捷的解析信息return shortcut;}// 依赖的类型Class<?> type = descriptor.getDependencyType();// <2> 获取注解中的 value 对应的值,例如 @Value、@Qualifier 注解配置的 value 属性值,注意 @Autowired 没有 value 属性配置Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);if (value != null) {if (value instanceof String) {// <2.1> 解析注解中的 value,因为可能是占位符,需要获取到相应的数据String strVal = resolveEmbeddedValue((String) value);BeanDefinition bd = (beanName != null && containsBean(beanName) ?getMergedBeanDefinition(beanName) : null);value = evaluateBeanDefinitionString(strVal, bd);}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());try {// <2.2> 进行类型转换,并返回return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());}catch (UnsupportedOperationException ex) {// A custom TypeConverter which does not support TypeDescriptor resolution...return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}}// <3> 解析复合的依赖对象(Array、Collection、Map 类型),获取该属性元素类型的 Bean 们// 底层和第 `4` 原理一样,这里会将 `descriptor` 封装成 MultiElementDescriptor 类型Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}// <4> 查找与类型相匹配的 Bean 们// 返回结果:key -> beanName;value -> 对应的 BeanMap<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);// <5> 如果一个都没找到if (matchingBeans.isEmpty()) {// <5.1> 如果 @Autowired 配置的 required 为 true,表示必须,则抛出异常if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}// <5.2> 否则,返回一个空对象return null;}String autowiredBeanName;Object instanceCandidate;// <6> 如果匹配的 Bean 有多个,则需要找出最优先的那个if (matchingBeans.size() > 1) {// <6.1> 找到最匹配的那个 Bean,通过 @Primary 或者 @Priority 来决定,或者通过名称决定autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {// <6.2> 如果没有找到最匹配的 Bean,则抛出 NoUniqueBeanDefinitionException 异常return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {// In case of an optional Collection/Map, silently ignore a non-unique case:// possibly it was meant to be an empty collection of multiple regular beans// (before 4.3 in particular when we didn\'t even look for collection beans).return null;}}// <6.3> 获取到最匹配的 Bean,传值引用给 `instanceCandidate`instanceCandidate = matchingBeans.get(autowiredBeanName);}// <7> 否则,只有一个 Bean,则直接使用其作为最匹配的 Beanelse {// We have exactly one match.Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}// <8> 将依赖注入的 Bean 的名称添加至方法入参 `autowiredBeanNames` 集合,里面保存依赖注入的 beanNameif (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}// <9> 如果匹配的 Bean 是 Class 对象,则根据其 beanName 依赖查找到对应的 Beanif (instanceCandidate instanceof Class) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;if (result instanceof NullBean) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}result = null;}if (!ClassUtils.isAssignableValue(type, result)) {throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());}// <10> 返回依赖注入的 Beanreturn result;}finally {// 设置当前线程的注入点为上一次的注入点,因为本次注入结束了ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}}

    依赖处理的过程稍微有点复杂,如下:

    1. 针对给定的工厂给定一个快捷实现的方式,暂时忽略

      例如考虑一些预先解析的信息,在进入所有 Bean 的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式

    2. 获取注解中的 value 对应的值,例如

      @Value

      @Qualifier

      注解配置的 value 属性值,注意 @Autowired 没有 value 属性配置

      解析注解中的 value,因为可能是占位符,需要获取到相应的数据

    3. 进行类型转换,并返回
  • 解析复合的依赖对象(Array、Collection、Map 类型),获取该属性元素类型的 Bean 们,调用

    resolveMultipleBeans(...)

    方法

    底层和下面第

    4

    步原理一样,这里会将

    descriptor

    封装成 MultiElementDescriptor 类型,如果找到了则直接返回

  • 查找与类型相匹配的 Bean 们,调用

    findAutowireCandidates(...)

    方法

    返回结果:key -> beanName;value -> 对应的 Bean

  • 如果一个都没找到

      如果

      @Autowired

      配置的 required 为 true,表示必须,则抛出异常

    1. 否则,返回一个空对象
  • 如果匹配的 Bean 有多个,则需要找出最优先的那个

      找到最匹配的那个 Bean,通过

      @Primary

      或者

      @Priority

      来决定,或者通过名称决定,调用

      determineAutowireCandidate(...)

      方法

    1. 如果没有找到最匹配的 Bean,则抛出 NoUniqueBeanDefinitionException 异常
    2. 获取到最匹配的 Bean,传值引用给
      instanceCandidate
  • 否则,只有一个 Bean,则直接使用其作为最匹配的 Bean

  • 将依赖注入的 Bean 的名称添加至方法入参

    autowiredBeanNames

    集合,里面保存依赖注入的 beanName

  • 如果匹配的 Bean 是 Class 对象,则根据其 beanName 依赖查找到对应的 Bean

  • 返回依赖注入的 Bean

  • 关于上面第

    3

    步对于符合依赖对象的处理这里不做详细分析,因为底层和第

    4

    步一样,接下来分析上面第

    4

    6

    步所调用的方法

    findAutowireCandidates 方法

    findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor)

    方法,找到符合条件的依赖注入的 Bean 们,如下:

    // DefaultListableBeanFactory.javaprotected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {// <1> 从当前上下文找到该类型的 Bean 们(根据类型)String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());// <2> 定义一个 Map 对象 `result`,用于保存符合条件的 BeanMap<String, Object> result = new LinkedHashMap<>(candidateNames.length);/*** <3> 遍历 Spring 内部已处理的依赖对象集合,可以跳到 AbstractApplicationContext#prepareBeanFactory 方法中看看* 会有一下几个内置处理对象:* BeanFactory 类型 -> 返回 DefaultListableBeanFactory* ResourceLoader、ApplicationEventPublisher、ApplicationContext 类型 ->  返回 ApplicationContext 对象*/for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {Class<?> autowiringType = classObjectEntry.getKey();if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue = classObjectEntry.getValue();autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}// <4> 遍历第 `1` 步找到的 Bean 的名称们for (String candidate : candidateNames) {// <4.1> 如果满足下面两个条件,则添加至 `result` 集合中if (!isSelfReference(beanName, candidate) // 如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)&& isAutowireCandidate(candidate, descriptor)) { // 符合注入的条件addCandidateEntry(result, candidate, descriptor, requiredType);}}// <5> 如果没有找到符合条件的 Bean,则再尝试获取if (result.isEmpty()) {boolean multiple = indicatesMultipleBeans(requiredType);// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();// <5.1> 再次遍历第 `1` 步找到的 Bean 的名称们for (String candidate : candidateNames) {// <5.2> 如果满足下面三个条件,则添加至 `result` 集合中if (!isSelfReference(beanName, candidate) // 如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)&& isAutowireCandidate(candidate, fallbackDescriptor) // 符合注入的条件&& (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) { // 不是复合类型,或者有 @Qualifier 注解addCandidateEntry(result, candidate, descriptor, requiredType);}}// <6> 如果还没有找到符合条件的 Bean,则再尝试获取// 和上面第 `5` 步的区别在于必须是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)if (result.isEmpty() && !multiple) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate)&& (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate))&& isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}// <7> 返回 `result`,符合条件的 Beanreturn result;}

    过程大致如下:

    1. 从当前上下文找到该类型的 Bean 们(根据类型

    2. 定义一个 Map 对象

      result

      ,用于保存符合条件的 Bean

    3. 遍历 Spring 内部已处理的依赖对象集合,例如你依赖注入 BeanFactory 类型的对象,则拿到的是 DefaultListableBeanFactory 对象,依赖注入 ResourceLoader、ApplicationEventPublisher、ApplicationContext 类型的对象, 拿到的就是当前 Spring 上下文 ApplicationContext 对象

    4. 遍历第

      1

      步找到的 Bean 的名称们

      如果满足下面两个条件,则添加至

      result

      集合中

      如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)、符合注入的条件

  • 如果没有找到符合条件的 Bean,则再尝试获取

      再次遍历第

      1

      步找到的 Bean 的名称们

    1. 如果满足下面三个条件,则添加至

      result

      集合中

      如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)、符合注入的条件、不是复合类型,或者有

      @Qualifier

      注解

  • 如果还没有找到符合条件的 Bean,则再尝试获取,和上面第

    5

    步的区别在于必须是自引用(这个 Bean 是在需要依赖它的 Bean 的内部定义的)

  • 返回

    result

    ,符合条件的 Bean

  • 总结下来:从当前上下文找到所有该类型的依赖注入对象然后返回,注意,如果你依赖注入的对象就是本身这个 Bean 内部定义的对象有特殊处理。

    例如注入一个集合对象,元素类型的 Bean 有一个是定义在本身这个 Bean 的内部,如果仅有这个 Bean 则会注入进行;如果除了本身这个 Bean 内部定义了,其他地方也定义了,那么本身这个 Bean 内部定义的 Bean 是不会被注入的;因为是自引用的 Bean 不会优先考虑,除非一个都没找到,才会尝试获取自引用的 Bean

    determineAutowireCandidate 方法

    determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor)

    方法,找到最匹配的那个依赖注入对象,如下:

    @Nullableprotected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {Class<?> requiredType = descriptor.getDependencyType();// <1> 尝试获取一个 @Primary 注解标注的 Bean,如果有找到多个则会抛出异常String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);// <2> 如果第 `1` 步找到了则直接返回if (primaryCandidate != null) {return primaryCandidate;}// <3> 尝试找到 @Priority 注解优先级最高的那个 Bean,如果存在相同的优先级则会抛出异常String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);// <4> 如果第 `3` 步找到了则直接返回if (priorityCandidate != null) {return priorityCandidate;}// Fallback// <5> 兜底方法,遍历所有的 Beanfor (Map.Entry<String, Object> entry : candidates.entrySet()) {String candidateName = entry.getKey();Object beanInstance = entry.getValue();// <5.1> 如果满足下面其中一个条件则直接返回if ((beanInstance != null&& this.resolvableDependencies.containsValue(beanInstance)) // 该 Bean 为 Spring 内部可处理的 Bean,例如 ApplicationContext|| matchesBeanName(candidateName, descriptor.getDependencyName())) { // 名称相匹配return candidateName;}}// <6> 上面都没选出来则返回一个空对象return null;}

    如果找到了多个匹配的依赖注入对象,则需要找到最匹配的那个 Bean,过程大致如下:

    1. 尝试获取一个
      @Primary

      注解标注的 Bean,如果有找到多个则会抛出异常

    2. 如果第
      1

      步找到了则直接返回

    3. 尝试找到
      @Priority

      注解优先级最高的那个 Bean,如果存在相同的优先级则会抛出异常

    4. 如果第
      3

      步找到了则直接返回

    5. 兜底方法,遍历所有的 Bean如果满足下面其中一个条件则直接返回:该 Bean 为 Spring 内部可处理的 Bean(例如 ApplicationContext、BeanFactory)、名称相匹配
  • 上面都没选出来则返回一个空对象
  • 总结

    本文讲述了

    @Autowired

    @Value

    @Resource

    等注解的实现原理,在《Bean 的创建过程》中我们可以了解到,在 Spring Bean 生命周期的很多阶段都可以通过相应的 BeanPostProcessor 处理器进行扩展,其中《Bean 的属性填充阶段》会通过

    InstantiationAwareBeanPostProcessor

    对 Bean 进行处理,有以下两个处理器:

    • AutowiredAnnotationBeanPostProcessor,主要处理
      @Autowired

      @Value

      注解进行依赖注入

    • CommonAnnotationBeanPostProcessor,主要处理
      @Resource

      注解进行依赖注入,以及

      @PostConstruct

      @PreDestroy

      生命周期注解的处理

    原理就是找到注解标注的字段(或方法),创建对应的注入元信息对象,然后根据该元信息对象进行注入(反射机制),底层都是通过

    DefaultListableBeanFactory#resolveDependency

    方法实现的,找到符合条件的 Bean(根据类型),然后筛选出最匹配的那个依赖注入对象。

    疑问:@Bean 等注解的实现原理又是怎样的呢?别急,在后续文章进行分析

    赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » 死磕Spring之IoC篇 – @Autowired 等注解的实现原理