05、Spring Boot,拆分配置文件以及配置类注解
Spring Boot    2019-07-25 23:00:32    582    0    0
acme   Spring Boot

    上次讲到了如何注入属性的值,如果将所有需要注入容器的值全部放入一个配置文件中,是否会让这个配置文件过于臃肿呢?

    那么,就使用@PropertySource这个注解来拆分配置文件,改注解的作用是告诉Spring Boot需要导入的配置文件的位置。

老样子,先上pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <parent>
  6.         <groupId>org.springframework.boot</groupId>
  7.         <artifactId>spring-boot-starter-parent</artifactId>
  8.         <version>2.1.6.RELEASE</version>
  9.         <relativePath/> <!-- lookup parent from repository -->
  10.     </parent>
  11.     <groupId>cc_acme</groupId>
  12.     <artifactId>springboot-split-properties</artifactId>
  13.     <version>0.0.1-SNAPSHOT</version>
  14.     <name>springboot-split-properties</name>
  15.     <description>Demo project for Spring Boot</description>
  16.  
  17.     <properties>
  18.         <java.version>1.8</java.version>
  19.     </properties>
  20.  
  21.     <dependencies>
  22.         <dependency>
  23.             <groupId>org.springframework.boot</groupId>
  24.             <artifactId>spring-boot-starter-web</artifactId>
  25.         </dependency>
  26.  
  27.         <dependency>
  28.             <groupId>org.springframework.boot</groupId>
  29.             <artifactId>spring-boot-configuration-processor</artifactId>
  30.             <optional>true</optional>
  31.         </dependency>
  32.  
  33.         <dependency>
  34.             <groupId>org.springframework.boot</groupId>
  35.             <artifactId>spring-boot-devtools</artifactId>
  36.             <scope>runtime</scope>
  37.             <optional>true</optional>
  38.         </dependency>
  39.         <dependency>
  40.             <groupId>org.springframework.boot</groupId>
  41.             <artifactId>spring-boot-starter-test</artifactId>
  42.             <scope>test</scope>
  43.         </dependency>
  44.     </dependencies>
  45.  
  46.     <build>
  47.         <plugins>
  48.             <plugin>
  49.                 <groupId>org.springframework.boot</groupId>
  50.                 <artifactId>spring-boot-maven-plugin</artifactId>
  51.             </plugin>
  52.         </plugins>
  53.     </build>
  54.  
  55. </project>

接着是配置文件application.properties,在这个配置文件中我只是加入了端口server.port=8080这个属性其实并没有作用,因为就是默认的,可以舍弃,加着只是方便看

  1. server.port=8080

再接着在resources目录下,与application.properties同级目录新建一个名为user.properties的配置文件

  1. user.id=1
  2. user.user-name=acme
  3. user.password=123

我们讲User类的值放在这个文件中,那么该如何将内容注入呢?

  1. package cc_acme.springbootsplitproperties.entity;
  2.  
  3.  
  4. import org.springframework.boot.context.properties.ConfigurationProperties;
  5. import org.springframework.context.annotation.PropertySource;
  6. import org.springframework.stereotype.Component;
  7.  
  8. /**
  9.  * User entity
  10.  *
  11.  * @author acme
  12.  * @ConfigurationProperties 注解用于标识注释参数 prefix标识对应的前缀
  13.  * @Component 标识注入Spring容器中(只有注入Spring容器才能使用)
  14.  */
  15. @PropertySource("classpath:user.properties")//加载指定的配置文件,也可以是数组导入多个配置文件
  16. @ConfigurationProperties(prefix = "user")
  17. @Component
  18. public class User {
  19.  
  20.     private Integer id;
  21.     private String userName;
  22.     private String password;
  23.  
  24.     @Override
  25.     public String toString() {
  26.         return "User{" +
  27.                 "id=" + id +
  28.                 ", userName='" + userName + '\'' +
  29.                 ", password='" + password + '\'' +
  30.                 '}';
  31.     }
  32.  
  33.     public Integer getId() {
  34.         return id;
  35.     }
  36.  
  37.     public void setId(Integer id) {
  38.         this.id = id;
  39.     }
  40.  
  41.     public String getUserName() {
  42.         return userName;
  43.     }
  44.  
  45.     public void setUserName(String userName) {
  46.         this.userName = userName;
  47.     }
  48.  
  49.     public String getPassword() {
  50.         return password;
  51.     }
  52.  
  53.     public void setPassword(String password) {
  54.         this.password = password;
  55.     }
  56. }

这个时候@PropertySource就产生了作用,最后来上测试类。

  1. package cc_acme.springbootsplitproperties;
  2.  
  3. import cc_acme.springbootsplitproperties.entity.User;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9.  
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class SpringbootSplitPropertiesApplicationTests {
  13.  
  14.     @Autowired
  15.     private User user;
  16.  
  17.     @Test
  18.     public void contextLoads() {
  19.         System.out.println(user);
  20.     }
  21.  
  22. }

看一下运行结果

属性的确注入其中了。

这个便是配置文件的简单拆分。

不过都到了这里,Spring Boot如何导入beans.xml呢?在很久很久以前,毕竟还是将值放入这个配置文件中的,下面又要用到一个新的注解,先卖个关子。

新建一个在resources目录下新建beans.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.  
  6.     <bean id="student" class="cc_acme.springbootsplitproperties.entity.Student">
  7.         <property name="id" value="2"/>
  8.         <property name="name" value="student"/>
  9.     </bean>
  10.  
  11. </beans>

在entity包下新建一个Student类

  1. package cc_acme.springbootsplitproperties.entity;
  2.  
  3. /**
  4.  * Student类
  5.  *
  6.  * @author acme
  7.  */
  8. public class Student {
  9.     private Integer id;
  10.  
  11.     private String name;
  12.  
  13.     @Override
  14.     public String toString() {
  15.         return "Student{" +
  16.                 "id=" + id +
  17.                 ", name='" + name + '\'' +
  18.                 '}';
  19.     }
  20.  
  21.     public Integer getId() {
  22.         return id;
  23.     }
  24.  
  25.     public void setId(Integer id) {
  26.         this.id = id;
  27.     }
  28.  
  29.     public String getName() {
  30.         return name;
  31.     }
  32.  
  33.     public void setName(String name) {
  34.         this.name = name;
  35.     }
  36. }

接着新建一个测试类StudentTest并且运行测试

  1. package cc_acme.springbootsplitproperties;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9.  
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class StudentTest {
  13.  
  14.     @Autowired
  15.     ApplicationContext applicationContext;
  16.  
  17.     @Test
  18.     public void testStudent() {
  19.         System.out.println(applicationContext.containsBean("student"));
  20.     }
  21.  
  22. }

运行的测试结果如下:

并没有加载beans.xml文件,其中配置的对象未被加载到容器中。

这个时候就需要用到@ImportResource注解,并且讲该注解放到程序入口上。

  1. package cc_acme.springbootsplitproperties;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.context.annotation.ImportResource;
  6.  
  7. @ImportResource("classpath:beans.xml")//也可以是数组导入多个配置文件
  8. @SpringBootApplication
  9. public class SpringbootSplitPropertiesApplication {
  10.  
  11.     public static void main(String[] args) {
  12.         SpringApplication.run(SpringbootSplitPropertiesApplication.class, args);
  13.     }
  14.  
  15. }

此时再运行测试类获取的结果

到了这里,其实还并没有结束。从上面那句很久很久以前就应该看出来,现在还有多少人愿意去用beans.xml配置文件?不是在很久很久以前,Spring Framework就已经开始官方建议使用注解来配置吗?再到后来的配置类。既然SpringBoot作为Spring现在主推的框架,官方会不推荐一波使用注解配置?

新建一个CustomerConfig配置类

  1. package cc_acme.springbootsplitproperties.config;
  2.  
  3. import cc_acme.springbootsplitproperties.entity.Customer;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6.  
  7. /**
  8.  * Customer配置类
  9.  *
  10.  * @author acme
  11.  */
  12. @Configuration//标识当前类是一个配置类
  13. public class CustomerConfig {
  14.     /**
  15.      * @return customer
  16.      * @Bean 注解用于标识该方法返回值添加到容器中,默认方法名便是id名
  17.      */
  18.     @Bean
  19.     public Customer customer() {
  20.         return new Customer();
  21.     }
  22.  
  23. }

在新建一个CustomerTest测试类

  1. package cc_acme.springbootsplitproperties;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9.  
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class CustomerTest {
  13.  
  14.     @Autowired
  15.     ApplicationContext applicationContext;
  16.  
  17.     @Test
  18.     public void testCustomer() {
  19.         System.out.println(applicationContext.containsBean("customer"));
  20.     }
  21. }

运行结果表明在容器中有customer这个bean,这也是现在Spring官方推荐的写法。

Pre: 06、Spring Boot,占位符

Next: 04、Spring Boot @Value和@Configurationproperties注解的区别

582
Table of content