初识Spring源码(1) -- applyMergedBeanDefinitionPostProcessors

0. 举个栗子:

 本版本源码为SpringBoot - 2.3.3.RELEASE,即spring-beans: 5.2.8.RELEASE
·
 主要通过学习@Autowired注入过程来学习Bean创建生命周期
·
 主要源码入口:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

@Component
public class SetterBean {

    @Autowired
    private BeanService beanService;
    
}

@Configuration
public class ConfigurationBean {
    @Bean
    public BeanService beanService() {
        BeanServiceImpl beanService = new BeanServiceImpl();
        beanService.setName("zhangsan");
        return beanService;
    }
}

 在createBeanInstance创建bean实例后(该方法简要可参考createBeanInstance基本功能
·
 会应用applyMergedBeanDefinitionPostProcessors这个后置处理器,去收集/预解析属性元数据

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
		
	... ... ... ...
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	
	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}
	... ... ... ...
}

1. applyMergedBeanDefinitionPostProcessors:

 这个方法本质就是调用MergedBeanDefinitionPostProcessor接口实现类的postProcessMergedBeanDefinition方法
·
 通过该方法去收集类中指定注解的属性元数据,这里主要分析AutowiredAnnotationBeanPostProcessor

  • AutowiredAnnotationBeanPostProcessor 支持@Autowired,@Value注解
  • CommonAnnotationBeanPostProcessor 支持@PostConstruct,@PreDestroy,@Resource注解
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);
		}
	}
}
 1.1. AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:

 主要通过findAutowiringMetadata方法去收集@Autowired,@Value注解的属性元数据

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}
  1.1.1. findAutowiringMetadata:

 先从缓存中查找有没有要注入的属性元数据对象InjectionMetadata,有则直接返回
 缓存没有,则经过双重校验后,去构建要注入属性的元数据;构建成功写入缓存

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// 先从缓存中查找有没有要注入的属性元数据,有则直接返回
	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;
}
  1.1.2. buildAutowiringMetadata:

 通过循环遍历类属性和方法,查找出指定注解注释的属性和方法,
 属性封装到AutowiredFieldElement,方法封装到AutowiredMethodElement,最后都封装到InjectionMetadata返回

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	// 不懂这个校验有什么用,感觉都不成立
	if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
		return InjectionMetadata.EMPTY;
	}

	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
	Class<?> targetClass = clazz;

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

		ReflectionUtils.doWithLocalFields(targetClass, field -> {
			// 循环遍历类属性,找到@Autowired,@Value注解的属性
			MergedAnnotation<?> ann = findAutowiredAnnotation(field);
			if (ann != null) {
				// 判断该属性是否是static修饰的,是的话则直接返回,可能导致该属性后续无法注入
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				// 判断属性是否是必须的,除非显示指定非必须@Autowired(required = false),默认是true
				boolean required = determineRequiredStatus(ann);
				// 找到指定注解的属性,封装成AutowiredFieldElement,然后添加到currElements
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});

		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			// 循环遍历类方法,找到@Autowired,@Value注解的方法
			MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				// 判断该方法是否是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);
					}
				}
				// 判断方法是否是必须的,除非显示指定非必须@Autowired(required = false),默认是true
				boolean required = determineRequiredStatus(ann);
				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
				// 找到指定注解的方法,封装成AutowiredMethodElement,然后添加到currElements
				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);
}
  1.1.3. ReflectionUtils#doWithLocalFields:

 和doWithLocalMethods方法一样,第二个参数是函数式接口

  • 循环遍历类属性,执行fc.doWith(field);,会触发回调函数方法
  • 在findAutowiredAnnotation方法查找该属性,是否被@Autowired,@Value注解

 这类函数式接口回调,在spring源码中很常见,也是很妙(doge)

public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
	for (Field field : getDeclaredFields(clazz)) {
		try {
			fc.doWith(field);
		}
		catch (IllegalAccessException ex) {
			throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
		}
	}
}
  1.1.4. populateBean:

 收集完的属性,会在属性填充方法populateBean里面进行依赖注入,本方法代码后续再详细介绍

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		... ... ...
		try {
			populateBean(beanName, mbd, instanceWrapper);
		... ... ...

 通过AutowiredAnnotationBeanPostProcessor#postProcessProperties方法,进行属性注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	... ... ...
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// 新版本调用postProcessProperties来进行依赖注入
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					// 兼容旧版本使用postProcessPropertyValues依赖注入
					pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
	}
	... ... ...

 上述applyMergedBeanDefinitionPostProcessors中已经完成属性元数据的预解析,所以能直接获取封装好的属性元数据数据

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	// 获取类中封装好的属性元数据数据
	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;
}

 关于属性填充和注入的详情,可查看文章:属性填充populateBean | 静态属性注入

  1.1.5. 小结:

 在createBeanInstance创建bean实例后(该方法简要可参考createBeanInstance基本功能
·
 会应用applyMergedBeanDefinitionPostProcessors这个后置处理器,去收集/预解析属性元数据
·
 通过循环遍历类属性和方法,找到有指定注解的属性,封装到注入元数据对象InjectionMetadata
·
 在属性填充populateBean时,从缓存中获取InjectionMetadata,进行注入

 1.2. CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:

 改方法会收集@PostConstruct 、@Resource的元数据信息

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	// 调用父类方法收集@PostConstruct元数据信息
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	// 通过findResourceMetadata方法去收集@Resource注解的属性元数据
	InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}
  1.2.1. findResourceMetadata:
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// 先从缓存中查找有没有要注入的属性元数据,有则直接返回
	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);
				}
				// 经过双重校验后,去构建标注@Resource属性的元数据
				metadata = buildResourceMetadata(clazz);
				// 构建完写入缓存,方便调用获取,防止重复解析
				this.injectionMetadataCache.put(cacheKey, metadata);
			}
		}
	}
	return metadata;
}
  1.2.2. buildResourceMetadata:

 通过循环遍历类属性和方法,查找出@Resource注解注释的属性和方法,
 都属性封装到ResourceElement,最后都封装到InjectionMetadata返回

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 (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
				if (Modifier.isStatic(field.getModifiers())) {
					throw new IllegalStateException("@EJB annotation is not supported on static fields");
				}
				currElements.add(new EjbRefElement(field, field, null));
			}
			// 上面的判断是处理EJB和WebServiceRef,反正我没用过也不晓得
			// 下面才是判断属性是不是@Resource标注的
			else if (field.isAnnotationPresent(Resource.class)) {
				// 判断该属性是否是static修饰的,是的话抛异常
				if (Modifier.isStatic(field.getModifiers())) {
					throw new IllegalStateException("@Resource annotation is not supported on static fields");
				}
				// 属性不是static修饰的,判断属性类型是不是javax.xml.ws.WebServiceContext
				// CommonAnnotationBeanPostProcessor初始化时会将WebServiceContext添加到ignoredResourceTypes
				if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
					// 条件符合,将属性封装成ResourceElement,再添加到currElements
					// ResourceElement构造函数会对member、name等进行赋值
					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))) {
				... ... ... // 省略EJB、webServiceRef的封装逻辑
				else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
					// 同样判断方法是不是static修饰的,是就抛异常
					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);
						// 找到指定注解的方法,封装成ResourceElement,然后添加到currElements
						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);
}
  1.2.3. ResourceElement:

 再这个构造函数里,这里会获取注解的属性值进行赋值(比如name)

public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
	// 会将属性(field)赋予内部属性member,还有方法类属性描述器赋值
	super(member, pd);
	Resource resource = ae.getAnnotation(Resource.class);
	// 获取@Resource(name = "beanService1")的name属性值;标注在方法的注解,则为方法名
	String resourceName = resource.name();
	// 获取@Resource(type = BeanService.class)的type属性值,默认Object类型
	Class<?> resourceType = resource.type();
	// 注解写了name,即resourceName非空,则isDefaultName=false
	this.isDefaultName = !StringUtils.hasLength(resourceName);
	if (this.isDefaultName) {
		// 注解不配置name,取要注入的属性的name
		resourceName = this.member.getName();
		// 处理方法上加注解的,方法名以set开头
		if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
			// 处理resourceName:截断set、转换首字母小写、连续大写则保留
			// 如:setAbcResource --> abcResource  ;		setABCResource	-->	ABCResource
			resourceName = Introspector.decapitalize(resourceName.substring(3));
		}
	}
	else if (embeddedValueResolver != null) {
		resourceName = embeddedValueResolver.resolveStringValue(resourceName);
	}
	// 不指定type属性,默认不成立,否则取检查指定的属性类型符不符合要注入的属性类型
	if (Object.class != resourceType) {
		checkResourceType(resourceType);
	}
	else {
		// 不指定type,默认取要注入的属性类型
		resourceType = getResourceType();
	}
	// 内部属性name、lookupType赋值
	this.name = (resourceName != null ? resourceName : "");
	this.lookupType = resourceType;
	// 获取@Resource(lookup = "beanService1")的lookup属性值,并赋值mappedName,默认是“”
	String lookupValue = resource.lookup();
	this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
	Lazy lazy = ae.getAnnotation(Lazy.class);
	// 属性或方法还标注有@Lazy,则lazyLookup=true,默认false
	this.lazyLookup = (lazy != null && lazy.value());
}

 关于@Resource的后续调用可查看:文章4.5节内容

 1.3. InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:

 和@Resource一样,这里会去收集@PostConstruct的方法元数据,主要通过findLifecycleMetadata取封装

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	LifecycleMetadata metadata = findLifecycleMetadata(beanType);
	metadata.checkConfigMembers(beanDefinition);
}
  1.3.1. findLifecycleMetadata:
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
	if (this.lifecycleMetadataCache == null) {
		// Happens after deserialization, during destruction...
		return buildLifecycleMetadata(clazz);
	}
	// 先从缓存中查找有没有要注入的方法元数据,有则直接返回
	LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
	if (metadata == null) {
		synchronized (this.lifecycleMetadataCache) {
			metadata = this.lifecycleMetadataCache.get(clazz);
			if (metadata == null) {
				// 经过双重校验后,去构建标注@PostConstruct方法的元数据
				metadata = buildLifecycleMetadata(clazz);
				// 构建完写入缓存,方便调用获取,防止重复解析
				this.lifecycleMetadataCache.put(clazz, metadata);
			}
			return metadata;
		}
	}
	return metadata;
}
  1.3.2. buildLifecycleMetadata:
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 -> {
			// 循环遍历类的方法,找到@PostConstruct标注的方法
			if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
				LifecycleElement element = new LifecycleElement(method);
				// 找到了@PostConstruct标注的方法,封装到LifecycleElement,再add进currInitMethods
				currInitMethods.add(element);
				if (logger.isTraceEnabled()) {
					logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
				}
			}
			// 和上面一样,这里是处理@PreDestory的,感觉少用不管他了
			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
		initMethods.addAll(0, currInitMethods);
		destroyMethods.addAll(currDestroyMethods);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);
	// 如果两个集合都是空,就返回空对象emptyLifecycleMetadata,否则封装到LifecycleMetadata
	return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
			new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
  1.3.3. LifecycleElement:
public LifecycleElement(Method method) {
	// 注解的方法是无参或多个参数则抛异常
	if (method.getParameterCount() != 0) {
		throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);
	}
	this.method = method;
	// 注解的方法是private修饰的,则identifier为方法完全限定名,否则就只有方法名
	this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
			ClassUtils.getQualifiedMethodName(method) : method.getName());
}

 关于@PostConstruct的后续调用可查看:文章4.6节内容

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值