SpringBoot2.x基础篇—常用注解(@Value&@ConfigurationProperties)

JAVA && Spring && SpringBoot2.x — 学习目录

SpringBoot2.x 读取自定义的yml配置到各种数据结构中

1. javaConfig配置

在最初,Spring使用XML配置文件的方式来描述bean的定义以及相互之间的依赖关系。但是会造成大量的XML文件,使项目变得越来越复杂且难以管理。后来Spring推出了JavaConfig项目——基于Java代码和Annotation注解来描述bean之间的依赖绑定关系。

  • 使用xml配置方式来描述bean的定义:
<bean id="bookService" class="cn.moondev.service.BookServiceImpl"></bean>
  • 基于JavaConfig的配置方式:
@Configuration
public class MoonBookConfiguration {

    // 任何标志了@Bean的方法,其返回值将作为一个bean注册到Spring的IOC容器中
    // 方法名默认成为该bean定义的id
    @Bean
    public BookService bookService() {
        return new BookServiceImpl();
    }
}

若是两个bean之间含有依赖

  • xml配置方式
<bean id="bookService" class="cn.moondev.service.BookServiceImpl">
    <property name="dependencyService" ref="dependencyService"/>
</bean>
<bean id="otherService" class="cn.moondev.service.OtherServiceImpl">
    <property name="dependencyService" ref="dependencyService"/>
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"/>
  • javaConfig中

如果一个bean依赖另一个bean,则直接调用对应javaConfig类中依赖bean的创建方法即可。

@Configuration
public class MoonBookConfiguration {

    // 如果一个bean依赖另一个bean,则直接调用对应JavaConfig类中依赖bean的创建方法即可
    // 这里直接调用dependencyService()
    @Bean
    public BookService bookService() {
        return new BookServiceImpl(dependencyService());
    }

    @Bean
    public OtherService otherService() {
        return new OtherServiceImpl(dependencyService());
    }

    @Bean
    public DependencyService dependencyService() {
        return new DependencyServiceImpl();
    }
}

有两个bean都依赖于dependencyService,也就是当初始化bookService时调用dependencyService(),在初始化otherService时调用dependencyService()。
注意:这时候IOC容器中还是有一个dependencyService实例

2. @ComponentScan

@ComponentScan注解对应XML配置形式中的元素,表示启用组件扫描。Spring会自动扫描注解配置的bean,然后将其注册到IOC容器中。

我们可以通过使用basePackages等属性来指定@ComponentScan自动扫描的范围,如果不指定,默认从声明@ComponentScan所在类的package进行扫描(当前包以及子包)。正因为这样,SpringBoot的启动类都默认推荐在src/main/java下。

3. @Import

@Import注解用于导入配置类,举个简单例子。

@Configuration
public class MoonBookConfiguration {
    @Bean
    public BookService bookService() {
        return new BookServiceImpl();
    }
}

现在还有一个配置类,比如MoonUserConfiguration,这个配置类中有一个bean依赖于MoonBookConfiguration中的bookService,那么如何将这两个bean组合在一起?借助@Import即可。

@Configuration
// 可以同时导入多个配置类,比如:@Import({A.class,B.class})
@Import(MoonBookConfiguration.class)
public class MoonUserConfiguration {
    @Bean
    public UserService userService(BookService bookService) {
        return new BookServiceImpl(bookService);
    }
}

注:在4.2之前,@Import注解只支持导入配置类。但是在4.2之后,它支持导入普通类,并将这个类作为一个bean的定义注册到IOC容器中。

4. @Value和@PropertySource("classpath:jdbc.properties")

@Value注解的作用就是讲配置文件中的属性读取出来,有@Value("${}")和@Value("#{}")两种方式。@PropertySource()注解一般用于来指定配置文件。

1. 使用@Value("${}")注解

@RestController
public class UserController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);

    @Value("${java.scheduled.validateTime}")
    private volatile String time;
}

2. 使用@Value("#{}")注解

@Component
public class ScheduledConfig {

    @Value("${java.scheduled.validateTime}")
    private String validateTime;

    @Value("${java.scheduled.validateExpression}")
    private String validateExpression;

    public String getValidateTime() {
        return validateTime;
    }

    public void setValidateTime(String validateTime) {
        this.validateTime = validateTime;
    }

    public String getValidateExpression() {
        return validateExpression;
    }

    public void setValidateExpression(String validateExpression) {
        this.validateExpression = validateExpression;
    }

}
@RestController
public class UserController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);

    @Value("#{scheduledConfig.validateTime}")
    private volatile String time;
}

5. @ConfigurationProperties和@EnableConfigurationProperties

当某些属性的值需要配置时,我们一般会在application.properties文件中新建配置项,然后在bean中使用@Value注解来获取配置的值,但是@Value的可扩展性较差,因为在每个地方都要写上@Value("xxx"),如果xxx字符串改变,每个地方都要改变。因此SpringBoot提供了更优雅的实现方式。那就是@ConfigurationProperties注解。

@Component
//  还可以通过@PropertySource("classpath:jdbc.properties")来指定配置文件
@ConfigurationProperties("jdbc.mysql")
// 前缀=jdbc.mysql,会在配置文件中寻找jdbc.mysql.*的配置项
pulic class JdbcConfig {
    public String url;
    public String username;
    public String password;
}
@Configuration
public class HikariDataSourceConfiguration {

    @AutoWired
    public JdbcConfig config;

    @Bean
    public HikariDataSource dataSource() {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(config.url);
        hikariConfig.setUsername(config.username);
        hikariConfig.setPassword(config.password);
        // 省略部分代码
        return new HikariDataSource(hikariConfig);
    }
}

@EnableConfigurationProperties注解表示对@ConfigurationProperties的内嵌支持,默认会将对应的Properties Class作为JavaBean注入到IOC容器中,即在响应的Properties类上不用加@Component注解。

6. 修改源码中的@ConfigurationProperties类

例如:源码中定义了一个配置:

package com.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties("jdbc.mysql")
public class JdbcConfig {

    public String url;
    public String username;
    public String password;

}

开发时,修改配置的前缀:

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestJdbcConfig {
    @Bean
    @ConfigurationProperties("my.jdbc.mysql")
    public JdbcConfig jdbcConfig() {
        return new JdbcConfig();
    }
    @Bean
    public HikariDataSource d1(@Qualifier("jdbcConfig") JdbcConfig config) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(config.url);
        hikariConfig.setUsername(config.username);
        hikariConfig.setPassword(config.password);
        // 省略部分代码
        return new HikariDataSource(hikariConfig);
    }
}

配置文件的使用:

my:
 jdbc:
  mysql:
   url: http://asasa
   username: xiaoming
   password: 123

这样的用途比如可以实现数据库的主从配置:


    /**
     * 配置master数据源
     */
    @Bean(name = "masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    public DataSource masterDataSource() {
        DataSource dataSource = DataSourceBuilder.create(this.getClass().getClassLoader())
                .type(com.alibaba.druid.pool.DruidDataSource.class).build();
        return dataSource;
    }

    /**
     * 配置slave数据源
     */
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid.slave")
    public DataSource slaveDataSource(@Autowired @Qualifier("masterDataSource") DataSource masterDataSource) {
        DataSource dataSource = DataSourceBuilder.create(this.getClass().getClassLoader())
                .type(com.alibaba.druid.pool.DruidDataSource.class).build();
        return dataSource;
    }

在配置文件中可以直接进行配置:

spring:
  datasource:
    name: mysql_test
    type: com.alibaba.druid.pool.DruidDataSource
    #druid相关配置
    druid:
      master:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/test_db?allowMultiQueries=true
        username: root
        password: 123qwe
        #初始化连接数
        initial-size: 10
        #最小活跃连接数
        min-size: 5
        #最大活跃连接数
        max-active: 30
        #获取连接的等待时间
        max-wait: 60000
      slave:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/exam?allowMultiQueries=true
        username: root
        password: 123qwe

这样做的好处是:子类若进行个性化扩展时,不必新建一个@ConfigurationProperties类,将所有的属性都拷贝进去。


IDEA 提示: Spring Boot Configuration Annotation Processor not fount in classpath解决方案

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-configuration-processor</artifactId> 
    <optional>true</optional> 
</dependency>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容