Spring扩展点总结
Spring扩展点梳理
-
BeanFactoryPostProcessor
- BeanDefinitionRegistryPostProcessor refresh() --> invokeBeanFactoryPostProcessor() 解析配置类
-
BeanPostProcessor
- InstantiationAwareBeanPostProcessor 实例化前后
- AbstractAutoProxyCreator AOP 动态代理
-
@Import 解析配置类会解析@Import注解
- ImportSelector
- DeferredImportSelector
- ImportBeanDefinitionRegistrar
-
Aware
-
- ApplicationContextAware
- BeanFactoryAware
-
InitializingBean || @PostConstruct
-
FactoryBean
-
SmartInitializingSingleton
-
ApplicationListener
-
Lifecycle
-
- SmartLifecycle refresh() —> finishRefresh() refresh()方法的最后会调用
- LifecycleProcessor
-
HandlerInterceptor SpringMVC的拦截器
-
MethodInterceptor AOP 方法拦截器
补充两个 SpringBoot启动完成最后的两个扩展点
- ApplicationRunner
- CommandLineRunner
整合Nacos
ApplicationListener扩展场景——监听容器中发布的事件
Nacos的服务注册,就是利用ApplicationListener来实现的
AbstractAutoServiceRegistration#onApplicationEvent
start() ---> register() --> ... -->
namingService.registerInstance(serviceId, group, instance);
Nacos的配置中心,在微服务这边为各个dataId添加监听器,也是利用的ApplicationListener
public class NacosContextRefresher implements ApplicationListener<ApplicationReadyEvent> , ApplicationContextAware {
// 在spring容器启动完成后就会调用该类的onApplicationEvent()方法
public void onApplicationEvent(ApplicationReadyEvent event) {
if (this.ready.compareAndSet(false, true)) {
// 给当前应用注册nacos监听器
// 就是遍历我们配置文件中定义的dataId 并为他们每一个都注册一个监听器,当配置中心的配置文件更改后进行更新本机内存数据
this.registerNacosListenersForApplications();
}
}
//......
}
Lifecycle扩展场景——管理具有启动、停止生命周期需求的对象
NacosWatch
订阅的服务实例更改事件
#对SmartLifecycle的扩展
NacosWatch#start
#订阅服务接收实例更改的事件
NamingService#subscribe
服务实例心跳
Nacos2.X版本的服务实例心跳机制也是基于SmartLifecycle
实现的
public class NacosDiscoveryHeartBeatPublisher implements ApplicationEventPublisherAware, SmartLifecycle {
//......
public void start() {
if (this.running.compareAndSet(false, true)) {
log.info("Start nacos heartBeat task scheduler.");
// 开始nacos心跳定时任务
this.heartBeatFuture = this.taskScheduler.scheduleWithFixedDelay(this::publishHeartBeat, Duration.ofMillis(this.nacosDiscoveryProperties.getWatchDelay()));
}
}
//......
}
整合Ribbon、LoadBalancer
SmartInitializingSingleton扩展场景—— 对容器中的Bean对象进行定制处理
思考:为什么@Bean修饰的RestTemplate加上@LoadBalanced就能实现负载均衡功能?
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
LoadBalancerAutoConfiguration
对SmartInitializingSingleton的扩展,为所有用@LoadBalanced修饰的restTemplate(利用了@Qualifier)绑定实现了负载均衡逻辑的拦截器LoadBalancerInterceptor
LoadBalancerInterceptor
整合Feign
@Import+FactoryBean的扩展场景——将接口生成的代理对象交给Spring管理
思考:为什么Feign接口可以通过@Autowired直接注入使用?Feign接口是如何交给Spring管理的?
@FeignClient(value = "mall-order",path = "/order")
public interface OrderFeignService {
@RequestMapping("/findOrderByUserId/{userId}")
R findOrderByUserId(@PathVariable("userId") Integer userId);
}
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
OrderFeignService orderFeignService;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
//feign调用
R result = orderFeignService.findOrderByUserId(id);
return result;
}
}
我们使用OpenFeign,都会在主启动类上面加上@EnableFeignClients
注解,而这其中就会使用@Import导入一个ImportBeanDefinitionRegistrar
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
//......
}
FeignClientsRegistrar
FeignClientFactorybean
整合Sentinel
HandlerInterceptor扩展场景——对mvc请求增强
实现详情请看《拦截器处理web请求》
AbstractSentinelInterceptor#preHandle 对所有接口进行资源保护的入口
public abstract class AbstractSentinelInterceptor implements HandlerInterceptor {
// ...
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// ......
String resourceName = this.getResourceName(request);
Entry entry = SphU.entry(resourceName, 1, EntryType.IN);
// ......
}
}
SmartInitializingSingleton&FactoryBean结合场景——根据类型动态装配对象
sentinel规则持久化部分,读数据源的创建就是利用了SmartInitializingSingleton+FactoryBean,根据类型动态装配对象
实现详情请看《 Sentinel持久化push推模式 --> 微服务端的实现 --> 微服务解析读数据源流程》
#Sentinel持久化读数据源设计,利用了SmartInitializingSingleton扩展点
SentinelDataSourceHandler#afterSingletonsInstantiated
# 注册一个FactoryBean类型的数据源
》SentinelDataSourceHandler#registerBean
》》NacosDataSourceFactoryBean#getObject
# 利用FactoryBean获取到读数据源
》》new NacosDataSource(properties, groupId, dataId, converter)
SentinelDataSourceHandler
NacosDataSourceFactoryBean
整合seata
详细实现过程查看《Seata全局事务源码 --> 源码入口》
AbstractAutoProxyCreator&MethodInterceptor结合场景——实现方法增强
GlobalTransactionScanner
GlobalTransactionalInterceptor