2.springboot-实现自动化配置的方法(springboot starter工作原理)

1.概述

  • springboot项目可通过配置文件进行一些参数配置,如数据库连接,redis连接等。在application.yml中配置这些参数后,参数就会自动生效,本文解析springboot如何实现自动化配置;
  • 一般情况下,每个种类的配置文件都会有对应的java配置类与之对应。如数据库连接配置,与之对应的是DataSourceProperties类。ide可直接通过点击配置文件链接到对应的java配置类;
  • 配置文件的加载可解析为两步。一是读取配置文件中的数据并绑定到java配置类,二是加载java配置类到spring容器中;

2.加载过程

2.1.读取配置文件

首先读取配置文件中的数据绑定到java配置类对应的属性中;

A.@Value注解

@Value单个注入配置文件的属性;

B.@ConfigurationProperties注解

@ConfigurationProperties批量注入配置文件的属性;

C.Environment.getProperty()方法

  • Environment对象可以通过依赖注入/实现EnvironmentAware接口获取;
  • Environment.getProperty()方法可以获取配置文件的属性,然后通过代码初始化到指定的变量;

2.2.加载配置bean

上一步把配置文件中配置的参数绑定到了java配置类,然后需要把java配置类加载到spring容器中,配置才会生效;

A.@Configuration注解

  • spring加载组件的注解包括@Configuration @Controller @Service @Repository @Component;
  • 加载组件注解功能基本都一样,根据字面意义标注不同的组件,提高代码可读性,加载配置一般使用@Configuration;
  • 注意: 使用加载组件注解,需要spring扫描到配置类,然后才会加载到spring容器中。所以适用于应用系统中使用,不适用于第三方类库项目中使用(因为应用系统中一般不会配置spring扫描第三方类库);

B.@EnableConfigurationProperties注解

  • @EnableConfigurationProperties注解可配置需要加载的配置类。无论配置类在哪里,spring只要能引用到该配置类,就能加载;
  • @EnableConfigurationProperties注解本身需要标注在spring能加载的类上面,才会生效;
  • 注意:@EnableConfigurationProperties可以加载应用系统中的配置类,也可加载第三方类库项目中的配置类。但是加载第三方类库项目中的配置类,需要标注此注解的类能被spring加载到

C.spring.factories配置文件

  • 自动化配置原理。简单来说,就是@EnableAutoConfiguration会扫描项目所有依赖包的spring.factories文件,把key=EnableAutoConfiguration的类加载到spring容器中;
  • 示例:在本项目创建resources/META-INF/spring.factories文件,并配置key=EnableAutoConfiguration的数据加载自定义的自动配置类
//**resources/META-INF/spring.factories配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.pings.spring.demo.cache.MyAutoConfiguration
  • @EnableAutoConfiguration会自动加载该配置类。在本项目中配置好后,其它项目引用本项目时,无需额外的配置,仍然有效,多数第三方类库会采用此方式;
  • 注意:自动化配置可以加载应用系统中的配置类,也可加载第三方类库项目中的配置类。但是应用系统中的配置类,采用前面两种方式更方便,一般应用于第三方类库项目中;

3.实例解析

我们以阿里的druid数据源为例,看看它如何实现自动化配置;

3.1.spring.factories

  • 上一节讲到,第三方类库一般都是通过spring.factories配置文件加载配置bean,便于用户引入后,不用添加额外的配置;
  • druid-spring-boot-starter包的META-INF目录下配置了spring.factories。DruidDataSourceAutoConfigure是的druid数据源自动配置的入口;
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

3.2.DruidDataSourceAutoConfigure

  • DruidDataSourceAutoConfigure是的druid数据源自动配置的入口;
  • @EnableConfigurationProperties注解加载了DruidStatProperties和DataSourceProperties两个配置类,获取用户配置的数据源参数。其中DataSourceProperties是spring提供的数据源配置,而DruidStatProperties是druid监控配置;
  • @Import注解导入druid依赖的其它配置类;
  • 注册DruidDataSourceWrapper数据源,并调用init初始化方法进行初始化设置。DruidDataSourceWrapper是DataSource的druid实现;
//**加载组件(此处不配置也可以加载该配置类)
@Configuration
//**引入了druid依赖才生效
@ConditionalOnClass(DruidDataSource.class)
//**在DataSourceAutoConfiguration自动化配置生效之前配置
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
//**加载DruidStatProperties和DataSourceProperties配置两个配置类
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
//**导入druid依赖的配置类
@Import({DruidSpringAopConfiguration.class,
    DruidStatViewServletConfiguration.class,
    DruidWebStatFilterConfiguration.class,
    DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {

    private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);

    //**注册DruidDataSourceWrapper数据源,并调用init初始化方法进行初始化设置
    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        LOGGER.info("Init DruidDataSource");
        return new DruidDataSourceWrapper();
    }
}

3.3.读取配置

  • druid读取配置文件有使用了多种方式;

A.DruidStatProperties

DruidStatProperties使用@ConfigurationProperties注解读取监控相关配置;

@ConfigurationProperties("spring.datasource.druid")
public class DruidStatProperties {
    ...
}

B.DruidDataSourceWrapper

  • 首先使用@ConfigurationProperties注解读取数据源相关配置;
@ConfigurationProperties("spring.datasource.druid")
class DruidDataSourceWrapper extends DruidDataSource implements InitializingBean 
    //**从DruidDataSource继承的属性也能通过@ConfigurationProperties注解读取配置
    ...
}
  • 然后使用代码从System获取取数据源相关配置覆盖@ConfigurationProperties注解读取的配置。比如设置启动参数-Ddruid.name=test,即可替换掉application.yml中配置的druid.name参数;
public class DruidDataSource {
    ...
    public DruidDataSource(boolean fairLock){
        super(fairLock);
        //**获取System的配置
        configFromPropety(System.getProperties());
    }

    public void configFromPropety(Properties properties) {
        //**如果System配置了druid.name,则替换掉@ConfigurationProperties注解读取的配置
        String property = properties.getProperty("druid.name");
        if (property != null) {
            this.setName(property);
        }
    }
    ...
}

4.补充说明

**-spring-boot-starter包的作用就是为了实现自动化配置;

  • spring-boot-starter包引入其依赖的包;
  • spring-boot-starter包有spring.factories配置,引入自动化配置的入口**AutoConfigure;
  • spring-boot-starter包有**AutoConfigure,读取配置文件配置,并加载其依赖的配置类;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值