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>