spring源码合并bean定义信息 applyMergedBeanDefinitionPostProcessors

spring源码合并bean定义信息 applyMergedBeanDefinitionPostProcessors,第1张

上篇咱们聊到了bean实例的创建,按照流程图上面接下来应该进行属性填充了。这在里咱们思考一个问题,咱们@Autowired,@Value,@Resource,@PostConstruct,@PreDestroy是什么时候处理的呢,假如xml中配置了,注解也配置了,应该怎么处理呢?

  1. AutowiredAnnotationBeanPostProcessor 处理@Autowired和@Value注解bean定义信息
  2. CommonAnnotationBeanPostProcessor 处理@Resource、@PostConstruct、@PreDestroy注解的bean定义信息
doCreateBean中 applyMergedBeanDefinitionPostProcessors
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;
	}
}
// 这里是为了解决循环依赖,提前把创建bean的工厂方法放到三级缓存
// 也就是如果需要代理会返回代理对象,如果不需要代理,返回前面创建的对象
//后面会单独了解循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));//添加到三级缓存
}
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof MergedBeanDefinitionPostProcessor) {
			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
			// CommonAnnotationBeanPostProcessor 处理的注解(@PostConstruct、@PreDestroy、@Resource、WebServiceRef、EJB)
			// AutowiredAnnotationBeanPostProcessor 处理的注解(@Autowired,@Value)
			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}
}

咱们这里先明确一个点,这里只是解析注解,并没有进行赋值 *** 作

MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition 执行bean定义信息合并

咱们主要了解上面说的两个类

CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 解析注解信息并添加到缓存

@Resource和Autowired很像

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	//解析@PostConstruct与@PreDestroy,并封装到Metadata中,把Metadata放到lifecycleMetadataCache
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	//解析@Resource注解
	InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
	// 检查的作用就是看看外部有没有已经配置了,如果配置了丢弃掉注解的配置
	metadata.checkConfigMembers(beanDefinition);
}
InitDestroyAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 解析初始化和销毁方法

这里处理的是@PostConstruct和@PreDestroy

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	LifecycleMetadata metadata = findLifecycleMetadata(beanType);
	metadata.checkConfigMembers(beanDefinition);
}
InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata查找返回注解元数据信息
// 获取@PostConstruct和@Destroy注解标注的方法,包括父类,然后放入缓存,方便下次获取
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
	// 这里只是做了一次检查,buildLifecycleMetadata是咱们重点关注的方法
	if (this.lifecycleMetadataCache == null) {
		return buildLifecycleMetadata(clazz);
	}
	LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
	if (metadata == null) {
		synchronized (this.lifecycleMetadataCache) {
			metadata = this.lifecycleMetadataCache.get(clazz);
			if (metadata == null) {
				// 构建元数据
				metadata = buildLifecycleMetadata(clazz);
				//这里大家可以想一个问题,为什么使用ConcurrentHashMap呢?
				//这个过程可能会涉及到并发修改,也有可能会改变目标类,哪种情况下会被更改呢?
				//为什么要修改目标类对象呢?
				this.lifecycleMetadataCache.put(clazz, metadata);
			}
			return metadata;
		}
	}
	return metadata;
}
InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata 构建元数据信息
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
	if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
		return this.emptyLifecycleMetadata;
	}
	// 存储@PostConstruct和@PreDestroy
	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注解,添加到当前类init集合中
			//setInitAnnotationType(PostConstruct.class);
			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);
				}
			}
			// 如果这个方法标注了@PreDestroy注解,添加到当前类destroy集合中
			//setDestroyAnnotationType(PreDestroy.class);
			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);
				}
			}
		});
		// 把当前类的@PostConstruct和@PreDestory添加到外部容器中,下面接下来继续找父类定义的信息注解信息
		initMethods.addAll(0, currInitMethods);
		destroyMethods.addAll(currDestroyMethods);
		//获取父类
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);
	// 如果找到初始化方法或者销毁方法,那么会创建一个生命周期元数据的包装类,包装所有init方法和destroy方法
	return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
			new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
metadata.checkConfigMembers(beanDefinition) 最终把合并后的放在成员中
// 如果beanDefinition中有配置,那么使用beanDefinition的,如果没有配置,使用注解配置的
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
	Set<LifecycleElement> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
	for (LifecycleElement element : this.initMethods) {
		//全限定类名+方法名
		String methodIdentifier = element.getIdentifier();
		//判断xml是否配置了init-method方法
		if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) { 
			beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
			//把检查后的方法添加到集合中
			checkedInitMethods.add(element); 
			if (logger.isTraceEnabled()) {
				logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
			}
		}
	}
	Set<LifecycleElement> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
	for (LifecycleElement element : this.destroyMethods) {
		String methodIdentifier = element.getIdentifier();
		if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
			beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
			checkedDestroyMethods.add(element);
			if (logger.isTraceEnabled()) {
				logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
			}
		}
	}
	// 最终把合并后的放在成员中
	this.checkedInitMethods = checkedInitMethods;
	this.checkedDestroyMethods = checkedDestroyMethods;
}
AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 解析注解信息并添加到缓存
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	// 获取@Autowired和@Value注解的元数据
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	//合并处理bean定义信息属性
	metadata.checkConfigMembers(beanDefinition);
}
findAutowiringMetadata 查找元数据信息
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
	// 获取cache key
	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);
			// 这个检查方法比较有意思,上面咱们说ConcurrentHashMap的时候提了几个疑问,这里就用到了
			// 判断的时候是根据==null || target != clazz 控制
			// 说明存在并发修改,个人猜测会涉及到代理对象 *** 作
			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(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) {
				// 验证注解不能标注在静态方法上
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				boolean required = determineRequiredStatus(ann);
				// 满足条件了加入到字段属性的集合中
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});

		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			//从这里可以看出,autowired是可以添加到方法上的
			MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				// 同样不能作用到静态方法上
				if (Modifier.isStatic(method.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static methods: " + method);
					}
					return;
				}
				if (method.getParameterCount() == 0) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation should only be used on methods with parameters: " +
								method);
					}
				}
				boolean required = determineRequiredStatus(ann);
				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
				currElements.add(new AutowiredMethodElement(method, required, pd));
			}
		});
		// 所有的方法和属性处理完添加到集合中,再继续处理父类
		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);
	// 最后返回
	return InjectionMetadata.forElements(elements, clazz);
}
metadata.checkConfigMembers(beanDefinition) 合并定义信息,其实就是过滤
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
	Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
	for (InjectedElement element : this.injectedElements) {
		Member member = element.getMember();
		// 判断是否是别的地方(xml)属性是有配置,如果配置了,沿用(非注解配置)其他的,如果没有配置,沿用注解的
		if (!beanDefinition.isExternallyManagedConfigMember(member)) {
			beanDefinition.registerExternallyManagedConfigMember(member);
			checkedElements.add(element);
		}
	}
	this.checkedElements = checkedElements;
}
总结

applyMergedBeanDefinitionPostProcessors就是解析对应注解标注的属性和方法,解析完之后返回元数据信息,然后放到缓存中,下次使用的时候直接获取
如果xml中配置了,注解也标注了,那么默认会丢弃掉注解的配置,也就是xml配置优先级比较高

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/742376.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存