Spring中的扩展点
spring容器启动时,会先解析BeanDefinition,然后生成BeanDefinition信息;再实例化生成bean对象,在这个过程中spring为我们提供了很多扩展点,来实现定制功能。
解析BeanDefinition阶段
1、BeanFactoryPostProcessor:bean工厂后置处理器,可以用来注册bean定义
2、BeanDefinitionRegistryPostProcessor: 可以用来注册、移除、修改bean定义
3、ImportBeanDefinitionRegistrar:通过@Import注解导入,可以用来注册bean定义
Bean的生命周期阶段
1、BeanPostProcessor:在创建Bean的过程中可以对实例化前后、属性赋值、初始化前后进行干预
2、Aware接口:比如BeanNameAware, BeanFactoryAware等等,在bean实例化过程中调用
3、FactoryBean:自定义一个特殊工厂bean对象
4、InitializingBean:在bean初始化时调用
Spring容器启动完成阶段
1、SmartInitializingSingleton:在容器启动完成时调用(getBean创建完bean时调用)
2、LifecycleProcessor:在容器完成刷新时调用
3、ApplicationContextEvent:发布容器刷新事件
推荐使用的扩展点
1、ImportBeanDefinitionRegistrar:通过@Import注解导入来注册bean定义
2、@PostConstruct:注解定义初始化方法
3、FactoryBean:将具体相同逻辑的类通过工厂bean来创建代理对象
4、ApplicationContextEvent:容器刷新事件
5、LifecycleProcessor:容器生命周期处理类
扩展点执行顺序及示例代码
1、解析BeanDefinition阶段:HelloService,HelloService1通过bean工厂后置处理器进行注册BeanDefinition
2、bean生命周期阶段:bean的后置处理器,加了判断,只有beanName是demoService时才处理
3、容器启动完成阶段:bean创建完成后会调用容器启动后的扩展点
定义四个bean
@Component
public class DemoService implements InitializingBean, BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, ApplicationContextAware {
private String name;
/**
* 推断构造方法
* 1、若在后置处理器指定了构造方法,则用指定的
* 2、若没有指定
* 2.1、无构造方法,则用默认无参构造方法
* 2.2、一个构造方法,则用这个
* 2.3、多个构造方法,若存在无参构造方法,则用无参的;如果没有则会报错,若用@Autowired修饰,则会用@Autowired修饰的
* DemoService则用了后置处理器指定的构造方法
* @param helloService1
*/
@Autowired
public DemoService(HelloService1 helloService1) {
System.out.println("DemoService 一参构造方法");
}
public DemoService(HelloService1 helloService1, HelloService2 helloService2) {
System.out.println("DemoService 二参构造方法");
}
public void test() {
System.out.println("demo test");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("【BeanClassLoaderAware】回调: " + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【BeanFactoryAware】回调: " + beanFactory.getClass());
}
@Override
public void setBeanName(String name) {
System.out.println("【BeanNameAware】回调: " + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("【ApplicationContextAware】回调: " + applicationContext);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean#afterPropertiesSet】初始化时调用");
}
@PostConstruct
// TODO 推荐使用
public void start() {
System.out.println("【CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization】@PostConstruct注解的方式初始化前调用");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class HelloService {
@Autowired
private DemoService demoService;
public void test() {
System.out.println("hello test");
}
}
public class HelloService1 {
public void test() {
System.out.println("hello1 test");
}
}
@Component
public class HelloService2 {
public void test() {
System.out.println("hello2 test");
}
}
解析BeanDefinition阶段的扩展点
public class DemoImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
// TODO 推荐使用
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(HelloService1.class);
beanDefinition.setScope("singleton");
registry.registerBeanDefinition("helloService1", beanDefinition);
System.out.println("【ImportBeanDefinitionRegistrar#registerBeanDefinitions】 helloService1注册完成");
}
}
@Component
public class DemoBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(HelloService.class);
beanDefinition.setScope("singleton");
beanDefinitionRegistry.registerBeanDefinition("helloService", beanDefinition);
System.out.println("【BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry】 helloService注册完成");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
BeanDefinition helloService = configurableListableBeanFactory.getBeanDefinition("helloService");
String scope = helloService.getScope();
System.out.println("【BeanDefinitionRegistryPostProcessor#postProcessBeanFactory】 获取helloService的 scope为" + scope);
}
}
bean生命周期阶段扩展点
@Component
public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
System.out.println("【InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation】实例化前调用");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
System.out.println("【InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation】实例化后调用2");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("name", "张三");
System.out.println("【InstantiationAwareBeanPostProcessor#postProcessProperties】属性赋值时调用");
return propertyValues;
}
return null;
}
}
@Component
public class DemoMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if ("demoService".equals(beanName)) {
System.out.println("【MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition】实例化后调用1");
}
}
}
@Component
public class DemoBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
System.out.println("【BeanPostProcessor#postProcessBeforeInitialization】初始化前调用");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
System.out.println("【BeanPostProcessor#postProcessAfterInitialization】初始化后调用");
}
return bean;
}
}
@Component
public class DemoSmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
System.out.println("【DemoSmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors】实例化自定义构造方法");
try {
Constructor<?> declaredConstructor = beanClass.getDeclaredConstructor(HelloService1.class, HelloService2.class);
return new Constructor<?>[] {declaredConstructor};
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return SmartInstantiationAwareBeanPostProcessor.super.determineCandidateConstructors(beanClass, beanName);
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
if ("demoService".equals(beanName)) {
System.out.println("【DemoSmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference】属性赋值用于解决循环依赖的回调");
}
return SmartInstantiationAwareBeanPostProcessor.super.getEarlyBeanReference(bean, beanName);
}
}
容器启动完成阶段扩展点
@Component
public class DemoSmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("【SmartInitializingSingleton#afterSingletonsInstantiated】容器启动完成执行");
}
}
@Component
public class DemoLifecycle implements SmartLifecycle {
// TODO 推荐使用
private boolean isRunning = false;
@Override
public void start() {
System.out.println("【SmartLifecycle#start】容器启动完成 执行Lifecycle start");
isRunning = true;
}
@Override
public void stop() {
System.out.println("【SmartLifecycle#stop】容器启动完成 执行Lifecycle stop");
isRunning = false;
}
@Override
public boolean isRunning() {
return isRunning;
}
}
@Component
public class DemoApplicationListener implements ApplicationListener<ApplicationEvent> {
// TODO 推荐使用
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("【ApplicationListener#onApplicationEvent】容器启动完成监听");
}
}
配置类和测试类
@ComponentScan("com.spring")
@Import(DemoImportBeanDefinitionRegistrar.class)
public class TestConfig {
}
public class TestMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TestConfig.class);
DemoService demoService = (DemoService)ctx.getBean("demoService");
demoService.test();
System.out.println(demoService.getName());
HelloService helloService = (HelloService)ctx.getBean("helloService");
HelloService1 helloService1 = (HelloService1)ctx.getBean("helloService1");
helloService.test();
helloService1.test();
}
}
执行结果如下
扩展点应用
微服务中服务注册实现
整合自动配置后,服务会自动注册到注册中心
整合Nacos
Spring容器启动完成阶段:ApplicationListener事件监听机制的应用
在自动配置类中定义了NacosServiceRegistryAutoConfiguration服务自动注册配置
在NacosServiceRegistryAutoConfiguration中定义了实现自动注册的NacosAutoServiceRegistration bean对象
@Bean
@ConditionalOnBean({AutoServiceRegistrationProperties.class})
public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
}
NacosAutoServiceRegistration类结构如下,该类实现了ApplicationListener监听,在spring容器启动完成后,会发布事件,监听器监听到事件后调用onApplicationEvent()方法,该方法最终会调用serviceRegistry.register实现服务注册
整合Eureka
Spring容器启动完成阶段:SmartLifecycle的应用
在自动配置类中定义了EurekaClientAutoConfiguration客户端自动配置类,在该配置类中定义了EurekaAutoServiceRegistration、EurekaServiceRegistry两个用于服务注册的bean
@Bean
public EurekaServiceRegistry eurekaServiceRegistry() {
return new EurekaServiceRegistry();
}
@Bean
@ConditionalOnBean({AutoServiceRegistrationProperties.class})
@ConditionalOnProperty(
value = {"spring.cloud.service-registry.auto-registration.enabled"},
matchIfMissing = true
)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
EurekaServerInitializerConfiguration类结构如下,实现了SmartLifecycle接口,在spring容器启动完成后会调用start()方法,该方法中会调用serviceRegistry.register完成服务注册
整合Consul
Spring容器启动完成阶段:ApplicationListener事件监听机制的应用
在自动配置类中定义了ConsulAutoServiceRegistrationAutoConfiguration客户端自动配置类,在该配置类中定义了ConsulAutoServiceRegistration用于服务注册的bean
@Bean
@ConditionalOnMissingBean
public ConsulAutoServiceRegistration consulAutoServiceRegistration(ConsulServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, ConsulDiscoveryProperties properties, ConsulAutoRegistration consulRegistration) {
return new ConsulAutoServiceRegistration(registry, autoServiceRegistrationProperties, properties, consulRegistration);
}
ConsulAutoServiceRegistration类结构如下,该类实现了ApplicationListener监听,在spring容器启动完成后,会发布事件,监听器监听到事件后调用onApplicationEvent()方法,该方法最终会调用serviceRegistry.register实现服务注册
整合Grpc
Spring容器启动完成阶段:SmartLifecycle的应用
GrpcServerAutoConfiguration服务端自动配置类,在该配置类中定义了GrpcServerLifecycle用来开启netty服务。
GrpcServerLifecycle 实现了SmartLifecycle接口,在spring容器启动完成后会调用start()方法,该方法中会调用createAndStartGrpcServer,最终在NettyServer#start方法开启netty服务。
@EnableConfigurationProperties
@ConditionalOnClass({Server.class})
@AutoConfigureAfter({GrpcCommonCodecAutoConfiguration.class})
public class GrpcServerAutoConfiguration {
@ConditionalOnMissingBean
@ConditionalOnBean({GrpcServerFactory.class})
@Bean
public GrpcServerLifecycle grpcServerLifecycle(GrpcServerFactory factory, GrpcServerProperties properties) {
return new GrpcServerLifecycle(factory, properties.getShutdownGracePeriod());
}
}
public class GrpcServerLifecycle implements SmartLifecycle {
public void start() {
try {
this.createAndStartGrpcServer();
} catch (IOException var2) {
throw new IllegalStateException("Failed to start the grpc server", var2);
}
}
}
整合Mybatis
解析BeanDefinition阶段:ImportBeanDefinitionRegistrar的应用
Bean的生命周期阶段:FactoryBean的应用
@Import({MapperScannerRegistrar.class})
public @interface MapperScan {
}
1、MapperScannerRegistrar属于ImportBeanDefinitionRegistrar,在解析配置类阶段调用,进行扫描包,找到符合的mapper类,并注册成bean定义,每个mapper对应一个MapperFactoryBean,这是个FactoryBean
2、生成bean时会调用MapperFactoryBean的getObject()来生成代理对象MapperProxy
3、方法执行时会调用MapperProxy#invoke方法,最终调用MapperProxy#invoke执行增删改查操作。
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
// 核心代码 注册bean定义
GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
definition.setBeanClass(MapperFactoryBean.Class)
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName())
}
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
}
整合Feign
解析BeanDefinition阶段:ImportBeanDefinitionRegistrar的应用
Bean的生命周期阶段:FactoryBean的应用
1、@EnableFeignClients注解开启客户端调用,该注解导入了@Import({FeignClientsRegistrar.class})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
........
}
2、FeignClientsRegistrar是一个ImportBeanDefinitionRegistrar,在解析配置类时会调用registerBeanDefinitions方法。先注册一个FeignClientSpecification类型的bean,再扫描@FeignClient修饰的接口,注册为FeignClientFactoryBean(这是个FactoryBean,该bean包含的属性有,url:请求地址、type:具体调用的接口,name:服务端服务名)。
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerDefaultConfiguration(metadata, registry);
this.registerFeignClients(metadata, registry);
}
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
definition.addPropertyValue("url", this.getUrl(attributes));
definition.addPropertyValue("path", this.getPath(attributes));
definition.addPropertyValue("type", className);
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
}
3、在bean创建时调用其getObject方法,然后生成代理类ReflectiveFeign(整合调用客户端LoadBalancerFeignClient以及Ribbon负载均衡);
4、最后执行方法调用时,会调用代理类invoke方法,再调用LoadBalancerFeignClient的execute方法,然后通过ribbon实现负载均衡
class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware {
private Class<?> type;
public Object getObject() throws Exception {
// 创建代理类和调用逻辑省略
return this.getTarget();
}
}
整合Sentinel
Bean的生命周期阶段:AOP的应用
SentinelResourceAspect通过aop来实现限流和熔断功能,对所有@SentinelResource注解的方法进行拦截处理
1、entry=SphU.entry
以责任链形式构建校验链条ProcessorSlotChain,然后依次调用entry方法,重要Slot说明
a、FlowSlot:获取流控规则配置进行校验,可以配置线程数或者QPS等;快速失败:使用滑动时间窗算法,Warm up:使用令牌桶算法,排队等待:漏桶算法
b、DegradeSlot:断路器规则,正常情况是关闭的,异常时会打开;如果超过熔断的时间周期则会改为半开状态,尝试着调用一次请求,若成功,则关闭;
2、执行目标方法
3、异常处理
a、BlockException:规则校验不通过会调用注解属性blockHandle的方法
b、Throwable:业务异常会调用注解属性fallback的方法
4、entry.exit
最后依次调用ProcessorSlotChain的exit方法,重要Slot说明
a、DegradeSlot:累加慢调用次数,如果断路器是关闭状态,慢调用次数超过配置次数阈值,则打开;如果断路器是半开状态,如果这次调用超过响应阈值,则打开断路器,如果没超过则关闭。
@EnableConfigurationProperties({SentinelProperties.class})
public class SentinelAutoConfiguration {
...
@Bean
@ConditionalOnMissingBean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
public void sentinelResourceAnnotationPointcut() {
}
@Around("sentinelResourceAnnotationPointcut()")
public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
try {
entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
Object result = pjp.proceed();
return var18;
} catch (BlockException var15) {
var18 = this.handleBlockException(pjp, annotation, var15);
return var18;
} catch (Throwable var16) {
var10 = this.handleFallback(pjp, annotation, var16);
} finally {
entry.exit(1, pjp.getArgs());
}
return var10;
}
}
Webflux与WebMvc
Bean的生命周期阶段:InitializingBean的应用
两个都有核心处理类HandlerMapping、HandlerAdapter
springMvc核心处理类在spring-webmvc包里,webflux处理类在spring-webflux包里
HandlerMapping、HandlerAdapter都实现了InitializingBean接口,在创建bean时会进行初始化,保存对应的映射关系,初始化处理器信息。
以解析@RequestMapping注解的两个处理类为例
1、RequestMappingInfoHandlerMapping,该类的抽象父类实现了InitializingBean,会在初始化时调用afterPropertiesSet来解析被@RequestMapping注解的方法,将其保存在map中
2、RequestMappingHandlerAdapter,在初始化时调用afterPropertiesSet来初始化参数处理器、返回值处理器等
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
}
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
// 参数解析器
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}//数据绑定器参数解析器
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}// 返回值处理器
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
}