Spring源码中的扩展点在SpringCloud组件中的实现

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

在这里插入图片描述



loadbalancer源码流程图



整合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

在这里插入图片描述



OpenFeign源码流程图 在线



整合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

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值