Spring扩展点系列-MergedBeanDefinitionPostProcessor
文章目录
- 简介
- 源码分析
- 示例
- 示例一:Spring中Autowire注解的依赖注入
简介
spring容器中Bean的生命周期内所有可扩展的点的调用顺序扩展接口 | 实现接口 |
---|---|
ApplicationContextlnitializer | initialize |
AbstractApplicationContext | refreshe |
BeanDefinitionRegistryPostProcessor | postProcessBeanDefinitionRegistry |
BeanDefinitionRegistryPostProcessor | postProcessBeanFactory |
BeanFactoryPostProcessor | postProcessBeanFactory |
instantiationAwareBeanPostProcessor | postProcessBeforelnstantiation |
SmartlnstantiationAwareBeanPostProcessor | determineCandidateConstructors |
MergedBeanDefinitionPostProcessor | postProcessMergedBeanDefinition |
InstantiationAwareBeanPostProcessor | postProcessAfterlnstantiation |
SmartInstantiationAwareBeanPostProcessor | getEarlyBeanReference |
BeanNameAware | setBeanName |
BeanFactoryAware | postProcessPropertyValues |
ApplicationContextAwareProcessor | invokeAwarelnterfaces |
InstantiationAwareBeanPostProcessor | postProcessBeforelnstantiation |
@PostConstruct | |
InitializingBean | afterPropertiesSet |
FactoryBean | getobject |
SmartlnitializingSingleton | afterSingletonslnstantiated |
CommandLineRunner | run |
DisposableBean | destroy |
MergedBeanDefinitionPostProcessor
扩展点的作用是对合并后的BeanDefintion进行后置处理。准确的调用时机应该是在创建完 bean 实例之后,接下来会对该接口源码和举例进行说明该扩展点的使用
源码分析
该接口的顶级接口是BeanPostProcessor
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {/*** Post-process the given merged bean definition for the specified bean.* @param beanDefinition 处理后bean definition* @param beanType 解析出来的 bean 的 class* @param beanName 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 bean 的名字* @since 5.1* @see DefaultListableBeanFactory#resetBeanDefinition*/default void resetBeanDefinition(String beanName) {}}
找到 applyMergedBeanDefinitionPostProcessors
可以看出, MergedBeanDefinitionPostProcessor 的调用是在创建完 bean 实例之后调用。applyMergedBeanDefinitionPostProcessors
方法会获取所有的 MergedBeanDefinitionPostProcessor,并回调它们的 postProcessMergedBeanDefinition 方法
回调 postProcessMergedBeanDefinition
方法时,已经拿到了 merged bean definition,并且还未开始 poplateBean 填充 bean 属性、initlializeBean 初始化 bean 对象,因此可以在这里对 merged bean definition 进行一些操作,在 poplateBean 或 initlializeBean 阶段使用前面操作结果实现所需功能
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}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;}}//.....源码省略
}protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);}
}
示例
示例一:Spring中Autowire注解的依赖注入
在Spring 中,AutowiredAnnotationBeanPostProcessor是MergedBeanDefinitionPostProcessor 的一个实现类,该类通过 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法回调获取 bean 上的 Autowire 注解,并将相关信息保存到缓存中。整体的主要作用是完成 Autowire 注解的依赖注入
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);//checkConfigMembers方法就是遍历从findAutowiringMetadata方法拿到的数据,返回封装这些数据,最后放入到RootBeanDefinition中,也就是bean定义信息中metadata.checkConfigMembers(beanDefinition);
}private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {// InjectionMetadata会被缓存起来--key为beanNameString 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);}//为当前bean构建InjectionMetadatametadata = buildAutowiringMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata;
}private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {// 构建currElements,用来存储符合条件的数据final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();//遍历当前类上所有属性,寻找到存在相关注解的属性ReflectionUtils.doWithLocalFields(targetClass, field -> {//findAutowiredAnnotation方法就是在遍历autowiredAnnotationTypes,判断参数或方法是否被autowiredAnnotationTypes里面的注解修饰,有就直接返回了。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));}});//遍历当前类上所有方法,寻找到存在相关注解的属性且非静态方法,然后封装为AutowiredMethodElement后返回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;}if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation should only be used on methods with parameters: " +method);}}// 获取required参数boolean required = determineRequiredStatus(ann);PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);// 添加到currElementscurrElements.add(new AutowiredMethodElement(method, required, pd));}});elements.addAll(0, currElements);//注入依赖注入一并处理当前父类上标注的相关依赖注入点targetClass = targetClass.getSuperclass();}// 向上遍历,直到父类为Object为止。while (targetClass != null && targetClass != Object.class);//创建一个InjectionMetadata返回,InjectionMetadata管理当前bean中所有依赖注入点return InjectionMetadata.forElements(elements, clazz);
}public void checkConfigMembers(RootBeanDefinition beanDefinition) {Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());for (InjectedElement element : this.injectedElements) {Member member = element.getMember();if (!beanDefinition.isExternallyManagedConfigMember(member)) {beanDefinition.registerExternallyManagedConfigMember(member);checkedElements.add(element);}}this.checkedElements = checkedElements;
}public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {//后续依赖注入只会对checkedElements集合中的依赖注入点进行处理Collection<InjectedElement> checkedElements = this.checkedElements;Collection<InjectedElement> elementsToIterate =(checkedElements != null ? checkedElements : this.injectedElements);if (!elementsToIterate.isEmpty()) {for (InjectedElement element : elementsToIterate) {element.inject(target, beanName, pvs);}}
}