天天看點

Spring 依賴注入源碼解析

接上一節内容,分析依賴注入和屬性填充

Spring 依賴注入源碼解析

貼上測試代碼:

@Component
//@Order(2)
public class Test {
   public String test = "test";
}
           
@Component
public class UserService implements InitializingBean, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware , ApplicationContextAware {


	@Autowired
	private Test test;

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("BeanNameAware.afterPropertiesSet()-------------");
	}

	public void test() {
		System.out.println("test");
	}

	@Override
	public void setBeanName(String name) {
		System.out.println("----BeanClassLoaderAware.setBeanClassLoader---");

	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		System.out.println("----BeanClassLoaderAware.setBeanClassLoader---");
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("----BeanFactoryAware.setBeanFactory---");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("----EnvironmentAware.setApplicationContext---");
	}

	@Override
	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		System.out.println("----EmbeddedValueResolverAware.setEmbeddedValueResolver----");

	}

	@Override
	public void setEnvironment(Environment environment) {
		System.out.println("----ApplicationContextAware.setEnvironment----");

	}
}
           
public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
//		TestBeanFactoryPostProcessor testBeanFactoryPostProcessor = new TestBeanFactoryPostProcessor();//要在執行個體化之前加入,還沒找到怎麼加入
//		applicationContext.addBeanFactoryPostProcessor(testBeanFactoryPostProcessor);
		UserService userService = applicationContext.getBean("userService", UserService.class);
		userService.test();

	}
}
           

我們的目的就是UserService中的

@Autowired
	private Test test;
           

是什麼時候注入的,是怎麼注入的。

總之Spring在屬性填充的時候,首先會去尋找注入點,然後根據注入點進行注入。

1.Spring 尋找注入點(@AutoWried @Resource @Value)

根據上一節的doCreateBean方法源碼開始:

doCreateBean方法屬性填充是在這一段

// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// 運作修改合并好了的BeanDefinition
					// 這裡會查找@Autowired的注入點(InjectedElement),并把這些注入點添加到mbd的屬性externallyManagedConfigMembers中
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 如果目前建立的是單例bean,并且允許循環依賴,并且還在建立過程中,那麼則提早暴露
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 此時的bean還沒有完成屬性注入,是一個非常簡單的對象
			// 構造一個對象工廠添加到singletonFactories中
			// 第四次調用後置處理器
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));  // AService
		}

		// Initialize the bean instance.
		// 對象已經暴露出去了
		Object exposedObject = bean;
		try {
			// 3、填充屬性 @Autowired
			populateBean(beanName, mbd, instanceWrapper);  //

			// 4、 初始化 和 BeanPostProcessor 正常AOP  BeanPostProcessor
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
           

第一段代碼非常重要

synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// 運作修改合并好了的BeanDefinition
					// 這裡會查找@Autowired的注入點(InjectedElement),并把這些注入點添加到mbd的屬性externallyManagedConfigMembers中
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}
           
protected 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源碼:
           
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

	/**
	 * Post-process the given merged bean definition for the specified bean.
	 * @param beanDefinition the merged bean definition for the bean
	 * @param beanType the actual type of the managed bean instance
	 * @param beanName the name of the bean
	 * @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
	 */
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

	/**
	 * A notification that the bean definition for the specified name has been reset,
	 * and that this post-processor should clear any metadata for the affected bean.
	 * <p>The default implementation is empty.
	 * @param beanName the name of the bean
	 * @since 5.1
	 * @see DefaultListableBeanFactory#resetBeanDefinition
	 */
	default void resetBeanDefinition(String beanName) {
	}

}
           

這個接口也是繼承BeanPostProcessor,是以也有該接口的功能。

這段代碼其實非常簡單,其實就是判斷BeanFactory裡面的beanPostProcessors是否有存在MergedBeanDefinitionPostProcessor類型的接口,然後調用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)

Spring 依賴注入源碼解析

現在我們來看這段代碼都做了什麼

利用debug模式打上條件斷點

Spring 依賴注入源碼解析

然後看一下BeanFactory裡面的beanPostProcessors有幾個後置處理器:

Spring 依賴注入源碼解析

兩個是自己加入的,其餘的是Spring 啟動的時候自己加入的(有幾個特别熟悉有沒有,在第一節我已經講過了)

符合bp instanceof MergedBeanDefinitionPostProcessor 的有:

1.CommonAnnotationBeanPostProcessor

2.AutowiredAnnotationBeanPostProcessor

3.AnnotationConfigApplicationContext

再看這個幾個類的postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)都做了什麼:

1.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName):

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
           

進入

super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
           
@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		metadata.checkConfigMembers(beanDefinition);
	}
           
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
		if (this.lifecycleMetadataCache == null) {
			// Happens after deserialization, during destruction...
			return buildLifecycleMetadata(clazz);
		}
		// Quick check on the concurrent map first, with minimal locking.
		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
		if (metadata == null) {
			synchronized (this.lifecycleMetadataCache) {
				metadata = this.lifecycleMetadataCache.get(clazz);
				if (metadata == null) {
					metadata = buildLifecycleMetadata(clazz);
					this.lifecycleMetadataCache.put(clazz, metadata);
				}
				return metadata;
			}
		}
		return metadata;
	}
           
Spring 依賴注入源碼解析

由上可知這個方法就是查詢父類的中繼資料資訊LifecycleMetadata。

我們在來他是怎麼拿出父類的資訊的,進入metadata = buildLifecycleMetadata(clazz);

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}

		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 (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
				new LifecycleMetadata(clazz, initMethods, destroyMethods));
	}
           

關鍵點:

targetClass = targetClass.getSuperclass();

while (targetClass != null && targetClass != Object.class);
           

其實就是一直循環取父類直到為null 和targetClass != Object.class(有空來測試繼承的情況)

這裡還有一個點就是:

AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType)
           
@Nullable
private Class<? extends Annotation> initAnnotationType;

@Nullable
private Class<? extends Annotation> destroyAnnotationType;
           
Spring 依賴注入源碼解析

很直覺的了解到,該方法還會去尋找初始方法和銷毀方法存入到LifecycleMetadata,也就是标注@PostConstruct和@PreDestroy的方法。

繼續往下面走:

InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
           
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String 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 = buildResourceMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

	private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		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 InjectionMetadata.forElements(elements, clazz);
	}
           

也是循環去找父類的@Resource注入點(字段和方法)還有幾個if else暫時不知道。

總而言之:

(1)該方法的主要作用是找出父類的LifecycleMetadata和标注@PostConstruct和@PreDestroy的方法注入點。

(2)找出字段和方法的@Resource注入點等一些操作。

2.AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName):

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		// 擷取beanType中的注入點
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
           
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String 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);
					}
					// 尋找目前clazz中的注入點,把所有注入點整合成為一個InjectionMetadata對象
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {

		// 判斷是不是候選者類,比如說類名,如果是以"java."開頭的則不是候選者類
		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<>();

			// 周遊屬性,看是否有@Autowired,@Value,@Inject注解
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				// 如果存在@Autowired,@Value,@Inject注解其中一個
				if (ann != null) {
					// 如果字段是static的,則直接進行傳回,不進行注入
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					// 是否required
					boolean required = determineRequiredStatus(ann);
					// 生成一個注入點AutowiredFieldElement
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			// 周遊方法,看是否有@Autowired,@Value,@Inject注解
			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;
					}
					// 方法參數值為0,不能用來注入屬性
					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();
		}
		while (targetClass != null && targetClass != Object.class);

		return InjectionMetadata.forElements(elements, clazz);
	}
           

其實從

InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata = buildAutowiringMetadata(clazz);
           

就可以看出就是在找@Autowire的注入點,但是值得注意得是還在找@Value的注入點(方法和字段,方法參數為0的時候不用來注入),當然也是循環也找父類的注入點。關鍵代碼如下:

AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes
           
Spring 依賴注入源碼解析
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
           
targetClass = targetClass.getSuperclass();
           
while (targetClass != null && targetClass != Object.class);
           

總而言之:該方法是尋找目前類及父類标注@Autowire和@Value的注入點(字段和方法)

3.AnnotationConfigApplicationContext.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName):

// 執行個體化之後,填充屬性之前會執行,會把某個ApplicationListener的bean的名字添加到singletonNames中去
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (ApplicationListener.class.isAssignableFrom(beanType)) {
			this.singletonNames.put(beanName, beanDefinition.isSingleton());
		}
	}
           

這個方法就不做過多解釋了。

2.上面已經找到注入點了,下面我們來分析怎麼注入的

直接F8跳到:

// 3、填充屬性 @Autowired
			populateBean(beanName, mbd, instanceWrapper);  
           

進入該方法,該方法裡面有一段:

for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

					// 調用BeanPostProcessor分别解析@Autowired、@Resource、@Value,得到屬性值
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
           

有沒有非常熟悉,其實主要的目的是周遊BeanFactory裡面的BeanPostProcessors,然後判斷

bp instanceof InstantiationAwareBeanPostProcessor
           

調用InstantiationAwareBeanPostProcessor.postProcessProperties方法,我們在看各個InstantiationAwareBeanPostProcessor都做了什麼

1.CommonAnnotationBeanPostProcessor.postProcessProperties:

@Override
	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;
	}
           
Spring 依賴注入源碼解析
Spring 依賴注入源碼解析

很直覺的了解到,這是對父類的屬性注入,還解析@Resource注入點注入:

@Override
		protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
			return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
					getResource(this, requestingBeanName));
		}
           
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);
	}
           
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;
	}
           
Spring 依賴注入源碼解析

繼續往下面走:

2.AutowiredAnnotationBeanPostProcessor.postProcessProperties

@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		// InjectionMetadata中儲存了所有被@Autowired注解标注的屬性/方法并封裝成一個個的InjectedElement
		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;
	}
           
// InjectionMetadata中儲存了所有被@Autowired注解标注的屬性/方法并封裝成一個個的InjectedElement
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
           
Spring 依賴注入源碼解析

這些注入點從哪裡來,不就是從上面合并出來的嘛

再次進入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()) {
			// 周遊每個能夠注入的屬性,進行注入
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				// element可能是Method,也可能是Field
				element.inject(target, beanName, pvs);
			}
		}
	}
           
@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				// 目前注入點已經注入過了,有緩存了,則利用cachedFieldValue去找對應的bean
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				//  Spring在真正查找屬性對應的對象之前, 會先将該屬性的描述封裝成一個DependencyDescriptor, 裡面儲存了Filed、是否強制需要即required, 以及屬性所在的類(即Field所在的類Class對象)
				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 {
					// 根據field去尋找合适的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依賴了哪些其他的bean的name
							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;
					}
				}
			}
			// 反射設值
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}
           

這個方法就是确定一個唯一的注入點确定值,有可能找到的是類,則需要

beanFactory.getBean(beanName);建立bean對象
           

然後通過反射的方式設定進去

這裡面存在一個問題就是,如何确定一個唯一的值,其實在DefaultListableBeanFactory工廠裡面有一個protected String determineAutowireCandidate(Map candidates, DependencyDescriptor descriptor)方法:

@Nullable
	protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
		Class<?> requiredType = descriptor.getDependencyType();

		// 取@Primary的bean
		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
		if (primaryCandidate != null) {
			return primaryCandidate;
		}

		// 取優先級最高的bean 通過@Priority來定義優先級,數字越小,優先級越高
		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
		if (priorityCandidate != null) {
			return priorityCandidate;
		}

		// Fallback
		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
			String candidateName = entry.getKey();
			Object beanInstance = entry.getValue();
			if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
					// 根據屬性名确定
					matchesBeanName(candidateName, descriptor.getDependencyName())) {
				return candidateName;
			}
		}
		return null;
	}
           

裡面有注釋可以自行觀看

其實該方法就是先去根據@Primary的bean确定唯一值,然後取優先級最高的bean 通過@Priority來定義優先級,數字越小,優先級越高,最後根據屬性名來确定。

3.對于自己重寫的InstantiationAwareBeanPostProcessor.postProcessProperties造成什麼樣的結果後續分析

總結:

1.通過内置的MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition方法尋找注入點

2.然後過内置InstantiationAwareBeanPostProcessor.postProcessProperties的方法進行屬性注入。

補充一個知識點:

父子BeanDefinition

父子BeanDefinition是Spring中的概念,Spring在根據BeanDefinition建立Bean的過程中,會先看目前BeanDefinition是否存在父BeanDefinition,如果存在則需要進行合并,合并就是把子BeanDefinition和父BeanDefinition中所定義的屬性整合起來(如果存在某個屬性在父子BeanDefinition中都存在,那麼取子BeanDefinition中的屬性)

網上找到的一個例子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="parent" abstract="true"
          class="com.dmz.official.merge.TestBean">
        <property name="name" value="parent"/>
        <property name="age" value="1"/>
    </bean>
    <bean id="child"
          class="com.dmz.official.merge.DerivedTestBean"
          parent="parent" >
        <property name="name" value="override"/>
    </bean>
</beans>
           
public class DerivedTestBean {
    private String name;

    private int age;

    // 省略getter setter方法
}

public class TestBean {
    private String name;

    private String age;

     // 省略getter setter方法
}

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("application.xml");
        DerivedTestBean derivedTestBean = (DerivedTestBean) cc.getBean("child");
        System.out.println("derivedTestBean的name = " + derivedTestBean.getName());
        System.out.println("derivedTestBean的age = " + derivedTestBean.getAge());
    }
}