@ConfigurationProperties注解使用方法(内含源代码)
源代码下载链接地址:
https://download.csdn.net/download/weixin_46411355/87400774
目录
- @ConfigurationProperties注解使用方法(内含源代码)
- `源代码下载链接地址:`[https://download.csdn.net/download/weixin_46411355/87400774](https://download.csdn.net/download/weixin_46411355/87400774)
- 前言
- 一、Spring配置方式
- 1.1 第一阶段:xml配置
- 1.2 第二阶段:注解配置
- 1.3 第三阶段:Java配置(java config)
- 二、@ConfigurationProperties使用方法
- 三、使用场景
- 3.1 作用于方法
- 3.1.1 使用场景(`配置读写分离`)
- 3.1.2 读写分离 案例实操
- 3.1.2.1 数据库的创建
- 3.1.2.2创建并搭建项目
- 3.1.2.3 添加依赖
- druid启动器的依赖
- MySQL 5 的依赖
- jpa的依赖 (spring-boot-starter-data-jpa)
- 3.1.2.4 JavaBean对象
- 3.1.2.5 application.properties配置文件
- 3.1.2.6 配置类
- 3.1.2.7 测试类
- 3.1.3问题与解答
- 问题:
- 解答与分析:
- 案例实操
- 3.2 作用于Class类及其用法
- 3.2.1 数据库的创建
- 3.2.2创建并搭建项目
- 3.2.3 添加依赖
- 3.2.3.1 druid启动器的依赖
- 3.2.3.2 MySQL 5 的依赖
- 3.2.3.3 jpa的依赖 (spring-boot-starter-data-jpa)
- 3.2.4 application.properties配置文件内容
- 3.2.5 JavaBean对象
- 3.2.6 Controller层
- 3.2.7运行启动类测试
- 四、总结
前言
最近在思考使用java config的方式进行配置,java config是指基于java配置的spring。传统的Spring一般都是基本xml配置的,后来spring3.0新增了许多java config的注解,特别是spring boot,基本都是清一色的java config。
一、Spring配置方式
1.1 第一阶段:xml配置
在spring 1.x时代,使用spring开发满眼都是xml配置的bean,随着项目的扩大,我们需要把xml配置文件分放到不同的配置文件中,那时候需要频繁地在开发的类和配置文件间切换。
1.2 第二阶段:注解配置
spring 2.x时代,随着JDK1.5带来的注解支持,spring提供了声明bean的注解,大大减少了配置量。这时spring圈子存在一种争论:注解配置和xml配置究竟哪个更好?我们最终的选择是应用
的基本配置用xml,业务配置用户注解。
1.3 第三阶段:Java配置(java config)
从spring 3.x到现在,spring提供了Java配置的能力。使用Java配置更好的理解配置的bean。
spring 4.x和spring boot都推荐使用Java配置
Spring IOC有一个非常核心的概念——Bean。由Spring容器来负责对Bean的实例化,装配和管理。
XML是用来描述Bean最为流行的配置方式。但随着Spring的日益发展,越来越多的人对Spring提出了批评。"Spring项目大量的滥用XML"就是最为严厉的一个批评。
由于Spring会把几乎所有的业务都以Bean的形式配置在XML文件中,造成了大量的XML文件。使用XML来配置Bean失去了编译时的类型安全检查。大量的XML配置使得整个项目变得更加复杂。
随着JAVA EE 5.0的发布,其中引入了一个非常重要的特性——Annotations(注释)。注释是源代码的标签,这些标签可以在源代码层进行处理或通过编译器把它融入到class文件中。在Java EE5以后的版本中,注释成为了一个主要的配置选项。
Spring使用注释来描述Bean的配置与采用XML相比,因为类注释是在一个类源代码中,可以获得类型安全检查的好处。可以良好的支持重构。
JavaConfig就是使用注释来描述Bean配置的组件。
JavaConfig是Spring的一个子项目,比起Spring,它还是一个非常年轻的项目。目前的版本是1.0 M2。使用XML来配置Bean所能实现的功能,通过JavaConfig同样可以很好的实现。
二、@ConfigurationProperties使用方法
下面具体讲一讲@ConfigurationProperties使用方法.
@ConfigurationProperties
Spring源码中大量使用了@ConfigurationProperties,比如server.port
就是由该注解获取到的,通过与其他注解配合使用,能够实现Bean的按需配置。
@ConfigurationProperties注解源码
可以看到,该注解有一个prefix
属性,通过指定的前缀,绑定配置文件中的配置,该注解可以放在类上,也可以放在方法上
。
我们来看一下注解说明
Annotation for externalized configuration. Add this to a class definition or a @Bean method in a @Configuration class if you want to bind and validate some external Properties (e.g. from a .properties file).
用于外部化配置的注释。如果您想绑定和验证一些外部属性(例如,从. Properties文件中),可以将此添加到类定义或@Configuration类中的@Bean方法中。
可以从注解说明中看到,当将该注解作用于方法上时,如果想要有效的绑定配置,那么该方法需要有@Bean注解且所属Class需要有@Configuration注解
简单一句话概括就是:Spring的有效运行是通过上下文(Bean容器)中Bean的配合的完成的,Bean可以简单理解成对象,有些对象需要指定字段内容,那么这些内容我们可以通过配置文件进行绑定,然后将此Bean归还给容器。
三、使用场景
3.1 作用于方法
3.1.1 使用场景(配置读写分离
)
比较常见的就是配置读写分离
的场景。
3.1.2 读写分离 案例实操
3.1.2.1 数据库的创建
数据库powernode_springboot-datasource-druid
表user
/*
Navicat Premium Data Transfer
Source Server : MySQL57_13306
Source Server Type : MySQL
Source Server Version : 50738
Source Host : localhost:13306
Source Schema : powernode_springboot-datasource-druid
Target Server Type : MySQL
Target Server Version : 50738
File Encoding : 65001
Date: 21/01/2023 12:02:32
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
drop database if exits `powernode_springboot-datasource-druid`
create database powernode_springboot-datasource-druid;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com');
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (4, 'Sandy', 21, 'test4@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
INSERT INTO `user` VALUES (6, 'HHH', 23, '3541434135@qq.com');
INSERT INTO `user` VALUES (7, 'Andy', 23, '3541434135@qq.com');
SET FOREIGN_KEY_CHECKS = 1;
3.1.2.2创建并搭建项目
3.1.2.3 添加依赖
druid启动器的依赖
<!--druid启动器-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
MySQL 5 的依赖
<!--mysql-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
jpa的依赖 (spring-boot-starter-data-jpa)
<!-- jpa依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
3.1.2.4 JavaBean对象
package com.bjpowernode.springboot02at_configurationproperties_anno04datasource.pojo;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.stereotype.Component;
import javax.persistence.criteria.CriteriaBuilder;
@Data
@Accessors(chain = true)
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
}
3.1.2.5 application.properties配置文件
#数据源
#写数据
spring.datasource.druid.write.url=jdbc:mysql://localhost:13306/powernode_springboot-datasource-druid
spring.datasource.druid.write.username=root
spring.datasource.druid.write.password=root
spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driver
#读数据
spring.datasource.druid.read.url=jdbc:mysql://localhost:13306/powernode_springboot-datasource-druid
spring.datasource.druid.read.username=root
spring.datasource.druid.read.password=root
spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver
3.1.2.6 配置类
DruidDataSourceConfig.java
package com.bjpowernode.springboot02at_configurationproperties_anno04datasource.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
@Configuration
public class DruidDataSourceConfig {
/**
* DataSource配置
* @return
*/
@Bean(name="readDruidDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.read")
public DataSource readDruidDataSource(){
return new DruidDataSource();
}
/**
* DataSource配置
* @return
*/
@Primary
@Bean(name = "writeDruidDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.write")
public DataSource writeDruidDataSource(){
return new DruidDataSource();
}
}
3.1.2.7 测试类
package com.bjpowernode.springboot02at_configurationproperties_anno04datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.bjpowernode.springboot02at_configurationproperties_anno04datasource.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.statements.SpringRepeat;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
class Springboot02AtConfigurationpropertiesAnno04DatasourceApplicationTests {
@Autowired
@Qualifier("readDruidDataSource")
private DruidDataSource readDruidDataSource;
@Test
public void testReadDataSource() throws SQLException {
System.out.println(readDruidDataSource);
System.out.println(readDruidDataSource.getClass().getName());
DruidPooledConnection connection = readDruidDataSource.getConnection();
System.out.println("connection = " + connection);
PreparedStatement preparedStatement = connection.prepareStatement("select * from user");
ResultSet resultSet = preparedStatement.executeQuery();
List<User> userList = new ArrayList<>();
while(resultSet.next()){
User user = new User();
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = (int)resultSet.getObject("age");
String email = resultSet.getObject("email").toString();
user.setId(id).setName(name).setAge(age).setEmail(email);
userList.add(user);
}
userList.forEach(System.out::println);
resultSet.close();
preparedStatement.close();
connection.close();
}
@Autowired
@Qualifier("writeDruidDataSource")
private DruidDataSource writeDruidDataSource;
@Test
public void testWriteDataSource() throws SQLException {
System.out.println(writeDruidDataSource);
System.out.println(writeDruidDataSource.getClass().getName());
DruidPooledConnection connection = writeDruidDataSource.getConnection();
System.out.println("connection = " + connection);
String insertSql = "insert into user values(?,?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(insertSql);
preparedStatement.setObject(1,null);
preparedStatement.setString(2,"Bob");
preparedStatement.setInt(3,23);
preparedStatement.setObject(4,"3541434135@qq.com");
int result= preparedStatement.executeUpdate();
System.out.println("result = " + result);
preparedStatement.close();
connection.close();
}
}
3.1.3问题与解答
问题:
也许有的人看到这里会比较疑惑,prefix并没有指定配置的全限定名,那它是怎么进行配置绑定的呢?
解答与分析:
相信大家肯定了解@Value注解
,它可以通过全限定名进行配置的绑定,
这里的 ConfigurationProperties其实就类似于使用多个@Value同时绑定 ,
绑定的对象就是DataSource类型的对象,而且是 隐式绑定 的,
意味着在配置文件编写的时候需要与对应类的字段名称 相同,
比如上述spring.datasource.druid.write.url=jdbc:mysql://localhost:13306/powernode_springboot-datasource-druid
,
当然了,你也可以随便写个配置,比如 spring.datasource.druid.write.uuu=www.baidu.com
,此时你 只需要在注解中加上以下参数即可
这个参数代表:忽略类中未知的属性
字段不匹配
- ignoreInvalidFields默认情况为true, 会自动忽略值类型不匹配的字段
- 当ignoreInvalidFields=false手动关闭时, 如果值类型不匹配将会爆出java.lang.IllegalStateException异常
案例实操
在配置文件中加上一行spring.datasource.druid.write.uuu=www.baidu.com
修改配置类的代码
在DruidDataSourceConfig.java类中
写Druid数据源writeDruidDataSource上的@ConfigurationProperties上增加一个参数ignoreUnknownFields其默认值为true代表忽略类中未知的属性,将其值设为false则代表不忽略类中未知的属性
执行测试类出现异常信息
以上就完成了多个数据源的配置,为读写分离做了铺垫
3.2 作用于Class类及其用法
3.2.1 数据库的创建
数据库powernode_springboot-datasource-druid
表user
/*
Navicat Premium Data Transfer
Source Server : MySQL57_13306
Source Server Type : MySQL
Source Server Version : 50738
Source Host : localhost:13306
Source Schema : powernode_springboot-datasource-druid
Target Server Type : MySQL
Target Server Version : 50738
File Encoding : 65001
Date: 21/01/2023 12:02:32
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
drop database if exits `powernode_springboot-datasource-druid`
create database powernode_springboot-datasource-druid;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com');
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (4, 'Sandy', 21, 'test4@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
INSERT INTO `user` VALUES (6, 'HHH', 23, '3541434135@qq.com');
INSERT INTO `user` VALUES (7, 'Andy', 23, '3541434135@qq.com');
SET FOREIGN_KEY_CHECKS = 1;
3.2.2创建并搭建项目
3.2.3 添加依赖
3.2.3.1 druid启动器的依赖
<!--druid启动器-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
3.2.3.2 MySQL 5 的依赖
<!--mysql-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
3.2.3.3 jpa的依赖 (spring-boot-starter-data-jpa)
<!-- jpa依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
3.2.4 application.properties配置文件内容
spring.datasource.url=jdbc:mysql://localhost:13306/powernode_springboot-datasource-druid?useUnicode=false&autoReconnect=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
3.2.5 JavaBean对象
package com.bjpowernode.springboot02at_configurationproperties_anno04datasourceatclass.pojo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "spring.datasource")
@Component
@Data
public class DataSourcePro {
private String url;
private String username;
private String password;
// 配置文件是driver-class-name,转驼峰命名便可以绑定成
private String driverClassName;
private String type;
}
3.2.6 Controller层
package com.bjpowernode.springboot02at_configurationproperties_anno04datasourceatclass.controller;
import com.bjpowernode.springboot02at_configurationproperties_anno04datasourceatclass.pojo.DataSourcePro;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/config")
public class ConfigurationPropertiesController {
@Autowired
private DataSourcePro dataSourcePro;
@GetMapping("/test")
public Map<String, Object> test(){
Map<String,Object> map = new HashMap<>();
map.put("url",dataSourcePro.getUrl());
map.put("username",dataSourcePro.getUsername());
map.put("password",dataSourcePro.getPassword());
map.put("driverClassName",dataSourcePro.getDriverClassName());
map.put("type",dataSourcePro.getType());
return map;
}
}
3.2.7运行启动类测试
浏览器输入localhost:8080/config/test
四、总结
@ConfigurationProperties
和 @value
有着相同的功能,但是 @ConfigurationProperties的写法更为方便
@ConfigurationProperties 的 POJO类的命名比较严格,因为它必须和prefix的后缀名要一致, 不然值会绑定不上, 特殊的后缀名是“driver-class-name”这种带横杠的情况,在POJO里面的命名规则是 下划线转驼峰 就可以绑定成功,所以就是 “driverClassName”