Spring Bean的配置绑定

您所在的位置:网站首页 config注解和bean Spring Bean的配置绑定

Spring Bean的配置绑定

#Spring Bean的配置绑定| 来源: 网络整理| 查看: 265

配置绑定的场景

最常见的配置绑定的场景,是在自定义的bean中通过@Value注解将某个属性和对应的配置绑定:

application.yml

di-task: root-path: "/usr/lib/cluster001/..."

某个bean

@Component public class TaskApplicationConfig { @Value("${di-task.root-path}") private String rootPath; ... }

在创建定时任务的bean时,使用的@Scheduled注解也可以通过相同的方式绑定配置,本质上和上面是相同的。

@Component public class InitStatTask { @Scheduled(cron = "${di-task.task.init-stat.cron}") public void initTask() { // do business } } 批量绑定

@ConfigurationProperties提供了更强大的功能,比如在我们需要批量绑定的时候,可以将多个配置项一起绑定到某个bean的多个属性上,而不用每一个属性都使用一个@Value注解:

@Component @ConfigurationProperties(prefix = "hbm") public class HbmConfig { /** * CM master 的IP */ private String agentHostIp; /** * CM master 的帐号. */ private String agentHostUser; /** * CM master 的密码. */ private String agentHostPassword; /** * CM master 的端口. */ private Integer sshdPort; // getters and setters }

这种定义,暗示着应用中存在下面的配置:

hbm: agent-host-ip: ... agent-host-user: ... agent-host-password: ... sshd-port: ...

这样,四个属性就可以一次性绑定到一个spring bean上。

为第三方依赖绑定配置

上面的示例,都有一个共同的特点:在自定义的bean中绑定配置。更直白一点,作为spring bean的代码是项目内的代码,不是第三方引入的依赖。

其中一个特征,就是我们直接在类上使用诸如@Component、@Service、@RestController的注解来声明为spring的bean。

如果是引入的第三方依赖,要实例化为spring的bean,需要我们自己进行配置。在当前项目环境中,这种类一般很少,直接写配置类就可以了:

@Configuration public class SomeConfig { @Bean public SomeType someType() { SomeType bean = new SomeType(); // init bean return bean; } }

只要这个配置类能被@SpringBootApplication或@ComponentScan扫描到,对应的bean就会被创建。

顺便提一下,如果我们在配置bean的时候,需要注入其他的bean依赖,可以将依赖作为参数。spring会根据类型和参数名来寻找对应的bean,然后作为参数参入进来:

@Configuration public class SomeConfig { @Bean public SomeType someType() { SomeType bean = new SomeType(); // init bean return bean; } @Bean public OtherType otherType(SomeType someType) { OtherType bean = new OtherType(); // init bean with some type return bean; } }

一个新的问题:当我们需要为第三方依赖的bean绑定配置的时候,应该如何做。

手工绑定

基于已有的知识,我们可以将配置项先绑定到自己的代码,然后再调用第三方依赖的setter方法,将对应的配置一一设置到bean中:

@Configuration @ConfigurationProperties(prefix = "some-type") public class SomeConfig { private String field1; private String field2; ... // getters and setters for field* @Bean public SomeType someType() { SomeType bean = new SomeType(); // init bean bean.setField1(field1); bean.setField2(field2); ... return bean; } }

对应的配置大概下面的样子:

some-type: field1: ... field2: ... 自动绑定

@ConfigurationProperties简化了这个工作,我们可以将它和@Bean一起使用,这种绑定的工作就会被自动完成:

@Configuration public class SomeConfig { @Bean @ConfigurationProperties(prefix = "some-type") public SomeType someType() { SomeType bean = new SomeType(); // init bean return bean; } }

spring会在someType()执行完之后,按照默认的绑定策略将配置绑定到返回的bean中。其效果和上文中我们逐个将配置绑定到bean中是一样的。

需要注意的是,spring按照setter的规范去绑定变量,配置的key和bean的setter方法要相呼应。比如某个bean有属性jdbcUrl,但对应的setter方法是setUrl,那么配置文件中应该配置的是url而不是jdbc-url。

如果setter方法在bean对应的类型的父类中,绑定同样有效。

可选择的绑定

我们可能会有不同的场景:允许用户选择使用哪一个数据源的实现,比如druid或者hikari。我们需要根据用户选择的数据源类型,来配置DataSource的实例化和参数绑定的动作。

换句话来说,上文中someType()方法可能返回的具体类型有多种,而使用@ConfigurationProperties的前提是我知道返回的具体是哪一种,以根据其setter方法设计对应的配置。所以我们所说的上述场景,就无法直接使用了。

选择并手工绑定

如果我们退一步,依然可以通过显示的逐个绑定来完成这项工作。首先,我们将所有的数据源类型的相关参数,都一一绑定到我们自己的类里面,然后在构造数据源Bean的时候,根据用户配置的类型来构建具体的数据源Bean,并将对应的配置参数通过setter方法进行设置。代码大意大概如下:

spring.datasource: type: druid druid: url: jdbc:hive2://10.3.70.118:10000 driver-class-name: org.apache.hive.jdbc.HiveDriver hikari: jdbc-url: jdbc:hive2://10.3.70.118:10000 driver-class-name: org.apache.hive.jdbc.HiveDriver connection-test-query: SELECT 'di-sql-engine'

你可能注意到druid和hikari的配置有些不同,这是与具体的实现类及其父类所提供的setter方法相关的。

@ConfigurationProperties(prefix = "spring.datasource.druid") public class DruidConfig { private String url; private String driverClassName; ... // getters and setters for field* } @ConfigurationProperties(prefix = "spring.datasource.hikari") public class HikariConfig { private String jdbcUrl; private String driverClassName; private String connectionTestQuery; ... // getters and setters for field* } @Configuration @ConfigurationProperties(prefix = "spring.datasource") public class SomeConfig { @Autowired private DruidConfig druidConfig; @Autowired private HikariConfig hikariConfig; private String type; ... // getters and setters for field* @Bean public DataSource datasource() { DataSource ds = null; switch(type) { case "druid": DruidDataSource druid = ... // init druid datasource druid.setUrl(druidConfig.getUrl); druid.setDriverClassName(druidConfig.getDriverClassName); ds = druid; break; case "hikari": // ... break; } ... return ds; } }

上面的代码应该可以自己想得到,它只是组合了我们已知的知识。

选择并自动绑定

但是在我们接触了自动绑定之后,再手动逐个绑定看起来有点蠢。接下来介绍另一种更加可控的自动绑定方式,帮助我们消除那些无聊的代码。

依然是基于同样的配置,我们可以这样编写配置类:

@Configuration @ConfigurationProperties(prefix = "spring.datasource") public class SomeConfig { @Autowired private Environment environment; private String type; ... // getters and setters for field* @Bean public DataSource datasource() { Class


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3