2.5、调用后置处理器

在idea中搜索了一下Spring的后置处理器(PostProcessor),找出了下图的几个

在这里插入图片描述
本文主要来分析红框中标出的两个,也就是在 refresh() 方法的第5步调用的后置处理器

1、后置处理器调用的时机

2、后置处理器调用的顺序

3、一个最重要的后置处理器

这个最重要的后置处理器就是 ConfigurationClassPostProcessor

1、ConfigurationClassPostProcessor的作用?

2、

4、案例读源码

(1)案例1

(2)案例2

(3)案例3

Spring Cloud中的案例一个,大家对Spring Cloud不熟悉没有关系,只需要关注Spring Framework部分就可以了

下面的代码是个 org.springframework.cloud.netflix.feign.ribbon包下的一个配置类(@Configuration),大家忽略Spring Cloud,就把它看做就是一个普通的配置类

@Configuration
class DefaultFeignLoadBalancedConfiguration {
	@Beand
	@ConditionalOnMissingBean
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
							  SpringClientFactory clientFactory) {
		return new LoadBalancerFeignClient(new Client.Default(null, null),
				cachingFactory, clientFactory);
	}
}

下面启动时,我们在下面的方法上打上条件断点:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass

在这里插入图片描述
调用栈如下

loadBeanDefinitionsForConfigurationClass:140, ConfigurationClassBeanDefinitionReader (o.s.context.annotation)
loadBeanDefinitions:116, ConfigurationClassBeanDefinitionReader (o.s.context.annotation)
processConfigBeanDefinitions:320, ConfigurationClassPostProcessor (o.s.context.annotation)
postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (o.s.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (o.s.context.support)
invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (o.s.context.support)
invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (o.s.context.support)
refresh:525, AbstractApplicationContext (o.s.context.support)
refresh:122, EmbeddedWebApplicationContext (o.s.boot.context.embedded)
refresh:693, SpringApplication (o.s.boot)
refreshContext:360, SpringApplication (o.s.boot)
run:303, SpringApplication (o.s.boot)
run:1118, SpringApplication (o.s.boot)
run:1107, SpringApplication (o.s.boot)
main:21, AppBMain (com.yh.stu)

几种注册BD的方式

1、硬编码
通过BeanDefinitionRegistry.registerBeanDefinition硬编码的方式进行注册,通常的做法有:
1、Spring 本身在实例化AnnotationConfigApplicationContext时,根据环境情况硬编码注册4~7个BD

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	...
	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, Object source) {
	...
	// 共注册了6个BD,即使通过
	RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	...
}
private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

	definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	registry.registerBeanDefinition(beanName, definition);
	return new BeanDefinitionHolder(definition, beanName);
}

我这里列出几个大家有个印象,后续用到这几个BD的时候知道怎么来的就可以了。

// 实现了两个接口:BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor
1:org.springframework.context.annotation.ConfigurationClassPostProcessor 
// 实现了BeanPostProcessor、BeanFactoryAware、PriorityOrdered接口
2:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 
// 同2一样,实现了BeanPostProcessor、BeanFactoryAware、PriorityOrdered接口
3:org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
// 同2一样,实现了BeanPostProcessor、BeanFactoryAware、PriorityOrdered接口
4:org.springframework.context.annotation.CommonAnnotationBeanPostProcessor 
// 实现了SmartInitializingSingleton, ApplicationContextAware 接口
5:org.springframework.context.event.EventListenerMethodProcessor 

6:org.springframework.context.event.DefaultEventListenerFactory 

❓ 1-这些Spring内部的 Bean是什么时候实例化的呢?
❓ 2-自定义的 BeanFacotryPostProcessor 是什么时候实例化的呢?

答1:
(1)、内部BeanFacotryPostProcessor 是在其被调用的时候利用容器(beanFactory.getBean(…))进行实例化的。
(和普通的Bean不一样,普通的Bean都是在refresh的第11阶段,即在finishBeanFactoryInitialization(beanFactory)方法中进行的)

//org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors){
	...
	// 从容器中找出所有 BeanDefinitionRegistryPostProcessor 类型的BD,后续按照顺序实例化并调用(PriorityOrdered/Ordered)
	String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
	for (String ppName : postProcessorNames) {
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			// 使用getBean来实例化Bean
			currentRegistryProcessors.add(
				beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
			processedBeans.add(ppName);
		}
	}
	...
}

(2)、AutowiredAnnotationBeanPostProcessor 是在 refresh的第 6 阶段,即在registerBeanPostProcessors(beanFactory)方法中实例化的

//org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors
public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	// 从容器中找出所有 BeanPostProcessor 类型的BD,后续按照顺序调用(PriorityOrdered/Ordered)
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
	...
	//遍历到 org.springframework.context.annotation.internalAutowiredAnnotationProcessor
	for (String ppName : postProcessorNames) {
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			// 使用getBean来实例化Bean
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		}
		...
	}

(3)同2一样
(4)同2一样
(5)EventListenerMethodProcessor 类的实例化时在refresh() 方法的第 11 阶段,即finishBeanFactoryInitialization(beanFactory) 方法中将其作为普通的Bean进行实例化

2、在容器中配置
Spring中配置Bean,在调用后置处理器 Configuration

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java硕哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值