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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容