天天看點

Spring源碼剖析-Autowired自動注入原理前言Bean的後置處理器屬性注入處理autowired總結

前言

這篇文章接上一篇文章屬性注入講一講 @Autowired 注解的實作源碼,這個也是面試被問的比較多的。

Bean的後置處理器

BeanPostProcessor 通常被叫做Bean的後置處理器,是Spring提供給我們的擴充接口,它允許我們在Bean調用初始化方法前,後對 Bean 做一些擴充邏輯。BeanPostProcessor提供了postProcessBeforeInitialization 前置處理和postProcessAfterInitialization後置處理 兩個方法,我們可以實作該接口,複寫這兩個方法來定義自己的邏輯,Bean的生命周期如下:

Spring源碼剖析-Autowired自動注入原理前言Bean的後置處理器屬性注入處理autowired總結

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor

是用來處理

@Autowired

注解注入的後置處理器,這裡先上一個 AutowiredAnnotationBeanPostProcessor的工作流程圖,後面可以根據這個圖來看源碼。

Spring源碼剖析-Autowired自動注入原理前言Bean的後置處理器屬性注入處理autowired總結

注冊AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor

是用來處理

@Autowired

注解注入的後置處理器,它是在

AbstractApplicationContext#refresh()

容器重新整理流程中

registerBeanPostProcessors()

方法中完成注冊,源碼如下

public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            //【第一步】Bean的加載和注冊
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //【第二步】注冊Bean後置處理器,注冊到DefaultListableBeanFactory(它的父類)中的一個List存放後置處理器
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                //【第三步】執行個體化單利且lazy-init=false的Bean
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }
           

上面标記了三個步驟:

  • ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory() : 加載解析注冊Bean
  • this.registerBeanPostProcessors(beanFactory) : 注冊BeanPostProcessors後置處理器
  • this.finishBeanFactoryInitialization(beanFactory):執行個體化Bean 以及屬性注入

我們現在來看一下 this.registerBeanPostProcessors(beanFactory) 注冊BeanPostProcessors後置處理器的源碼

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}
           

通過PostProcessorRegistrationDelegate去注冊

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		//後置處理器個數
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		//把BeanPostProcessorChecker後置處理器添加IOC容器中 , 它是用來執行個體化期間建立 bean 時記錄資訊消息,當  bean 沒有資格被所有 BeanPostProcessor 處理時。
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
		//實作 PriorityOrdered、 // Ordered 和其餘的 BeanPostProcessor。
		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.

		//實作了 priorityOrdered 接口的優先級最高的處理器,PriorityOrdered是Ordered接口的擴充,表示優先級排序:
		// PriorityOrdered對象總是在普通Ordered對象之前應用
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		//架構内部後置處理器
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		//具有排序的後置處理器,實作了Ordered 接口,order值越小,越先執行
		List<String> orderedPostProcessorNames = new ArrayList<>();
		//沒有指定順序的後置處理器
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();

		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//得到後置處理器Bean的執行個體
				AutowiredAnnotationBeanPostProcessor在這裡被執行個體化
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				//如果是實作了 PriorityOrdered 的後置處理器,添加到priorityOrderedPostProcessors集合中
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					//合并BeanDefinition的後置處理器
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				//添加實作了 Ordered 的後置處理器
				orderedPostProcessorNames.add(ppName);
			}
			else {
				//沒有任何順序的後置處理器
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		//首先,注冊實作 PriorityOrdered 的 BeanPostProcessors。
		//後置處理器排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//注冊priorityOrdered後置處理器
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		//接下來,注冊實作 Ordered 的 BeanPostProcessors。
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
		//處理實作了 ordered的後置處理器
		for (String ppName : orderedPostProcessorNames) {
			//得到後置處理器Bean
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			//添加到集合中
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//排序後置處理器
		sortPostProcessors(orderedPostProcessors, beanFactory);
		//注冊後置初期
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		//現在,注冊所有正常 BeanPostProcessor。
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		//
		for (String ppName : nonOrderedPostProcessorNames) {
			//得到Bean的執行個體
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//注冊正常後置處理器
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		//最後,重新注冊所有内部 BeanPostProcessor。
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		//ApplicationListener檢測器,也是一個BeanPostProcessor
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
           

這裡根據類型:

BeanPostProcessor.class

找到了所有的後置處理器,然後通過

beanFactory.getBean

建立Bean的執行個體,根據優先級依次注冊到

AbstractBeanFactory

中的

List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>()

集合中 , 注冊順序如下:

  1. 注冊實作了PriorityOrdered 接口的優先級最高的後置處理器
  2. 注冊實作了 Ordered接口的有序的後置處理器
  3. 注冊正常後置處理器
  4. 注冊内部使用的後置處理器MergedBeanDefinitionPostProcessor

對于AutowiredAnnotationBeanPostProcessor而言,它是屬于PriorityOrdered的範疇,優先被注冊,我們來看一下他的構造器

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

	...省略...


	/**
	 * Create a new AutowiredAnnotationBeanPostProcessor
	 * for Spring's standard {@link Autowired} annotation.
	 * <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
	 */
	 //為 Spring 的标準Autowired注釋建立一個新的 AutowiredAnnotationBeanPostProcessor
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
		//增加要注入的注解類型
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			//支援 JSR-330 的javax.inject.Inject注釋
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.info("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注釋下面是繼承體系圖:

Spring源碼剖析-Autowired自動注入原理前言Bean的後置處理器屬性注入處理autowired總結

屬性注入

上面我們知道了 AutowiredAnnotationBeanPostProcessor 是在什麼時候被執行個體化和被注冊到IOC容器中,接下來我們來分析一下 AutowiredAnnotationBeanPostProcessor 的工作流程。

前面文章我們分析過IOC啟動流程,在refresh()中

  • 調用 obtainFreshBeanFactory(); 對Bean進行加載,解析,注冊
  • 調用registerBeanPostProcessors(beanFactory); 注冊後置處理器
  • 調用 this.finishBeanFactoryInitialization(beanFactory); 對單利Bean進行建立。Bean建立成功後,會進行屬性注入, 屬性注入是在 AbstractAutowireCapableBeanFactory#populateBean 中完成。

我們今天要研究的@Autowire 注解的處理就是在populateBean方法中完成的。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	//省略....
	if (hasInstAwareBpps) {
			//得到所有的後置處理器
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//如果是InstantiationAwareBeanPostProcessor類型
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;					
					//後置處理器處理屬性【AutowireAnnotationBeanPostProcess就是在這裡調用】
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return;
					}
				}
			}
		}
           

處理autowired

下面是:AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 源碼

@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
		//查找找 autowire 中繼資料,利用反射根據bean的class得到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;
	}
           

這裡首先通過findAutowiringMetadata方法查找autowire的元注解資訊InjectionMetadata,然後調用InjectionMetadata.inject 執行注入,跟一下findAutowiringMetadata方法,

查找元注解

AutowiredAnnotationBeanPostProcessor#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.
		//擷取Bean的名字,如果沒有以類名作為名字
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		//從 自動注入中繼資料緩存map中查找InjectionMetadata
		// 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;
	}
           

查找元注解比較簡單,先從緩存中擷取,如果緩存中沒有就調用 buildAutowiringMetadata 查找元注解資訊然後加入緩存。

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();

			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//查找@autowired注解的屬性,以及要注入的對象
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					//添加到 currElements 集合中
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			...省略...,        
		//把注解封的屬性封裝成jectionMetadata
		return new InjectionMetadata(clazz, elements);
	}

           

根據Bean的class使用反射查找到Bean中的@Autowire注解資訊,以及注入的Bean ,建立成 一個一個的AutowiredFieldElement ,封裝到InjectionMetadata 傳回。Element結構如下:

Spring源碼剖析-Autowired自動注入原理前言Bean的後置處理器屬性注入處理autowired總結

屬性注入

我們接着看一下 InjectionMetadata#inject 注入方法

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()) {
			boolean debug = logger.isDebugEnabled();
			for (InjectedElement element : elementsToIterate) {
				if (debug) {
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				}
				//調用InjectedElement的inject方法注入
				element.inject(target, beanName, pvs);
			}
		}
	}
           

這裡得到了Bean的依賴的屬性,即InjectedElement 集合,然後一個一個調用inject進行注入值。代碼來到:AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				//DependencyDescriptor 依賴描述符
				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 {
					//得到容器中的Bean執行個體
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					if (!this.cached) {
						//走緩存流程
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							//注冊依賴的Bean
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {									
									
									//ShortcutDependencyDescriptor:具有預先解析的目标 bean 名稱的 DependencyDescriptor 變體
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				//【重要】給autoware的字段設定值 , 完成自動注入
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}
           

自動注入完成,再往後就是走 applyPropertyValues 流程,這個在之前已經分析過,這裡就不多解釋了。

總結

到這裡 autowaire自動注入的源碼流程就分析完了,這裡稍微總結一下

  1. AutowiredAnnotationBeanPostProcessor 在 AbstractApplicationContext#refresh() 容器重新整理流程中,将Bean的加載過程完成後 ,調用 PostProcessorRegistrationDelegate#registerBeanPostProcessors 來注冊到IOC容器的一個List中。
  2. 在AbstractApplicationContext#refresh() 容器重新整理流程中,會調用finishBeanFactoryInitialization來執行個體化單利的Bean。最終走到 AbstractAutowireCapableBeanFactory#doCreateBean 中進行Bean的建立以及調用populateBean方法進行屬性的注入。
  3. 屬性注入方法中會從IOC容器中得到所有的後置處理器,其中就包括 AutowiredAnnotationBeanPostProcessor,然後調用 postProcessPropertyValues 進行 autowire 自動注入。
  4. AutowiredAnnotationBeanPostProcessor利用反射得到autowire元注解資訊,得到需要注入的bean,封裝成InjectionMetadata
  5. 調用 InjectionMetadata.inject 進行自動注入,最終走到AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject中
  6. AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject方法中通過beanFactory.resolveDependency :解析注入的Bean,得到Bean的執行個體 ,然後通過反射機制給autowire的字段注入Bean的執行個體。

文章結束,喜歡就給個一鍵三連吧,你的肯定是我最大的動力,點贊上一千我就是腦癱也出下章

繼續閱讀