美文网首页纪年系列
【手记】微服务实践手记(7)

【手记】微服务实践手记(7)

作者: 楠瓜团子 | 来源:发表于2021-08-30 18:18 被阅读0次

    1.

    基于 @SpringBootApplication 注解实现自动配置的基本过程和原理。

    1)@SpringBootApplication

    创建项目会默认生成,在启动类上会看到这个注解。

    位于 spring-boot-autoconfigure 工程的org.springframework.boot.autoconfigure 包中。

    由3个注解组成:@SpringBootConfiguration、@EnableAutoConfiguration 和 @ComponentScan

    可以通过 exclude 和 excludeName 属性来配置不需要实现自动装配的类或类名,也可以通过 scanBasePackages 和 scanBasePackageClasses 属性来配置需要进行扫描的包路径和类路径。

    2)@ComponentScan

    批量扫描Bean并注入到容器中

    3)@SpringBootConfiguration

    提供JavaConfig配置类的实现

    4)@EnableAutoConfiguration

    在这个注解中有两个注解:@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)

    5)@Import

    属性中可以设置需要引入的类名,根据该类的不同类型,Spring 容器针对 @Import 注解有以下四种处理方式:

    如果该类实现了 ImportSelector 接口,Spring 容器就会实例化该类,并且调用其 selectImports 方法;

    如果该类实现了 DeferredImportSelector 接口,则 Spring 容器也会实例化该类并调用其 selectImports方法。DeferredImportSelector 继承了 ImportSelector,区别在于 DeferredImportSelector 实例的 selectImports 方法调用时机晚于 ImportSelector 的实例,要等到 @Configuration 注解中相关的业务全部都处理完了才会调用;

    如果该类实现了 ImportBeanDefinitionRegistrar 接口,Spring 容器就会实例化该类,并且调用其 registerBeanDefinitions 方法;

    如果该类没有实现上述三种接口中的任何一个,Spring 容器就会直接实例化该类。

    6) AutoConfigurationPackages.Registrar 类

    这个类是@AutoConfigurationPackage注解中@Import(AutoConfigurationPackages.Registrar.class)注解里使用到的类,遵循第三种情况,实现ImportBeanDefinitionRegistrar接口,并重写registerBeanDefinitions方法。这个方法的逻辑是先判断整个 Bean 有没有被注册,如果已经注册则获取 Bean 的定义,通过 Bean 获取构造函数的参数并添加参数值;如果没有,则创建一个新的 Bean 的定义,设置 Bean 的类型为 AutoConfigurationPackages 类型并进行 Bean 的注册。

    7)AutoConfigurationImportSelector类

    在@EnableAutoConfiguration的@Import(AutoConfigurationImportSelector.class)使用到

    实现DeferredImportSelector接口,符合第二规则

    负责从各种配置项中找到需要导入的具体配置类

    依赖的最关键组件就是 SpringFactoriesLoader

    2.

    上面的东西总结就是:注册Bean+导入配置类。接着就提到了JDK 中的 SPI 机制,原文这样说的:

    JDK 提供了用于服务查找的一个工具类 java.util.ServiceLoader 来实现 SPI 机制。当服务提供者提供了服务接口的一种实现之后,我们可以在 jar 包的 META-INF/services/ 目录下创建一个以服务接口命名的文件,该文件里配置着一组 Key-Value,用于指定服务接口与实现该服务接口具体实现类的映射关系。而当外部程序装配这个 jar 包时,就能通过该 jar 包 META-INF/services/ 目录中的配置文件找到具体的实现类名,并装载实例化,从而完成模块的注入。SPI 提供了一种约定,基于该约定就能很好地找到服务接口的实现类,而不需要在代码里硬编码指定。

    我认为的意思就是:

    接口实例化使用哪个实现类,不在代码里指定,在文件里指定。有哪些使用场景吗?有用过的留言说说。

    SpringFactoriesLoader用的就是SPI机制,查找所有 META-INF/spring.factories 文件夹中的配置文件,并把 Key 为 EnableAutoConfiguration 所对应的配置项通过反射实例化为配置类并加载到容器中。

    流程是跟着看了一遍,但是没啥感觉,平时还是在配置文件里写配置,看来还需要更多的经验啊。

    3.

    关于默认配置,提到了一个注解@ConditionalOn,常见的一些:

    @ConditionalOnProperty:只有当所提供的属性属于 true 时才会实例化 Bean

    @ConditionalOnBean:只有在当前上下文中存在某个对象时才会实例化 Bean

    @ConditionalOnClass:只有当某个 Class 位于类路径上时才会实例化 Bean

    @ConditionalOnExpression:只有当表达式为 true 的时候才会实例化 Bean

    @ConditionalOnMissingBean:只有在当前上下文中不存在某个对象时才会实例化 Bean

    @ConditionalOnMissingClass:只有当某个 Class 在类路径上不存在的时候才会实例化 Bean

    @ConditionalOnNotWebApplication:只有当不是 Web 应用时才会实例化 Bean

    自动配置可以提高系统的扩展性,许是没有太多的架构设计经验,限制了我的思路,多多学习吧。

    相关文章

      网友评论

        本文标题:【手记】微服务实践手记(7)

        本文链接:https://www.haomeiwen.com/subject/ljuoiltx.html