Bootstrap

spring中的扩展点及其应用

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);
		}
	}
}
;