1. 導入 Spring 配置
默認情況下,Spring Boot 中是不包含任何的 Spring 配置文件的,即使我們手動添加 Spring 配置文件到項目中,也不會被識別。那么 Spring Boot 項目如何導入 Spring 配置?
Spring Boot 為了我們提供了以下 2 種方式來導入 Spring 配置:
使用 @ImportResource 注解加載 Spring 配置文件
使用全注解方式加載 Spring 配置
1) @ImportResource 導入 Spring 配置文件
在主啟動類上使用 @ImportResource 注解可以導入一個或多個 Spring 配置文件,並使其中的內容生效。
示例,在 “ Springboot基礎知識(01)- Spring Boot 簡介、配置 Spring Boot 和 Spring Initializr ” 里 SpringbootBasic 項目基礎上,修改如下。
(1) 創建 src/main/java/com/example/entity/Person.java 文件
1 package com.example.entity; 2 3 import java.util.Date; 4 import java.util.List; 5 import java.util.Map; 6 import org.springframework.stereotype.Component; 7 import org.springframework.boot.context.properties.ConfigurationProperties; 8 9 public class Person { 10 private String firstName; 11 private Integer age; 12 private Boolean male; 13 private Date birth; 14 private Map<String, Object> maps; 15 private List<Object> lists; 16 private Dog dog; 17 public Person() { 18 } 19 public Person(String firstName, Integer age, Boolean male, Date birth, 20 Map<String, Object> maps, List<Object> lists, Dog dog) { 21 this.firstName = firstName; 22 this.age = age; 23 this.male = male; 24 this.birth = birth; 25 this.maps = maps; 26 this.lists = lists; 27 this.dog = dog; 28 } 29 30 // 省略 getter 和 setter 方法 31 32 @Override 33 public String toString() { 34 return "Person {" + 35 "firstName = '" + firstName + '\'' + 36 ", age = " + age + 37 ", male = " + male + 38 ", birth = " + birth + 39 ", maps = " + maps + 40 ", lists = " + lists + 41 ", dog = " + dog + 42 '}'; 43 } 44 }
(2) 創建 src/main/java/com/example/service/PersonService.java 文件
1 package com.example.service; 2 3 import com.example.entity.Person; 4 5 public interface PersonService { 6 public Person getPersonInfo(); 7 }
(3) 創建 src/main/java/com/example/service/PersonServiceImpl.java 文件
1 package com.example.service; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import com.example.entity.Person; 5 6 public class PersonServiceImpl implements PersonService { 7 @Autowired 8 private Person person; 9 @Override 10 public Person getPersonInfo() { 11 return person; 12 } 13 }
(4) 創建 src/main/resources/spring-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 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <bean id="personService" class="com.example.service.PersonServiceImpl"></bean> 8 </beans>
(5) 創建 src/main/java/com/example/ApplicationContextUtils.java 文件
1 package com.example; 2 3 import org.springframework.beans.BeansException; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.ApplicationContextAware; 6 import org.springframework.stereotype.Component; 7 8 /* 9 * 在非 SpringBoot 工廠管理的普通類中,如果要獲取工廠管理的對象,不能再使用 @Autowired 等注入的注解, 10 * SpringBoot 提供了一個 “ApplicationContextAware” 接口,實現此接口,即可獲取工廠管理的全部內容。 11 */ 12 @Component 13 public class ApplicationContextUtils implements ApplicationContextAware { 14 private static ApplicationContext applicationContext; 15 16 @Override 17 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 18 this.applicationContext = applicationContext; 19 } 20 21 // 通過屬性名查詢對象 22 public static Boolean containsBean(String id){ 23 return applicationContext.containsBean(id); 24 } 25 26 // 通過屬性名獲取對象 27 public static Object getbyId(String id){ 28 Object bean = applicationContext.getBean(id); 29 return bean; 30 } 31 32 ... 33 }
(6) 修改 src/main/java/com/example/App.java 文件
1 package com.example; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6 @SpringBootApplication 7 public class App { 8 9 public static void main(String[] args) { 10 SpringApplication.run(App.class, args); 11 12 Boolean b = ApplicationContextUtils.containsBean("personService"); 13 if (b) { 14 System.out.println("personService in IOC"); 15 } else { 16 System.out.println("personService not in IOC"); 17 } 18 } 19 20 }
運行:
personService not in IOC
(7) 在 App 類上使用 @ImportResource 注解,將 Spring 配置文件 beans.xml 加載到項目中,代碼如下。
1 ... 2 3 import org.springframework.context.annotation.ImportResource; 4 5 // 將 beans.xml 加載到項目中 6 @ImportResource(locations = {"classpath:/spring-beans.xml"}) 7 @SpringBootApplication 8 public class App { 9 public static void main(String[] args) { 10 ... 11 } 12 }
再運行:
personService in IOC
2) 全注解方式加載 Spring 配置
Spring Boot 推薦使用全注解的方式加載 Spring 配置,其實現方式如下:
(1) 使用 @Configuration 注解定義配置類,替換 Spring 的配置文件;
(2) 配置類內部定義一個或多個被 @Bean 注解的方法;
(3) AnnotationConfigApplicationContext 或 AnnotationConfigWebApplicationContext 類掃描和構建 bean 定義(相當於 Spring 配置文件中的<bean></bean>標簽);
(4) @Bean 注解方法的返回值以組件的形式添加到容器中,組件的 id 就是方法名。
示例,在上文 SpringbootBasic 項目基礎上,修改如下。
(1) 創建 src/main/java/com/example/AppConfig.java 文件
1 package com.example; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 6 import com.example.service.PersonService; 7 import com.example.service.PersonServiceImpl; 8 9 @Configuration 10 public class AppConfig { 11 12 /** 13 * 相當於 <bean id="personService" class="com.example.service.PersonServiceImpl"></bean> 14 */ 15 @Bean 16 public PersonService personService() { 17 return new PersonServiceImpl(); 18 } 19 20 }
(2) 修改 src/main/java/com/example/App.java 文件
1 package com.example; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6 @SpringBootApplication 7 public class App { 8 9 public static void main(String[] args) { 10 SpringApplication.run(App.class, args); 11 12 Boolean b = ApplicationContextUtils.containsBean("personService"); 13 if (b) { 14 System.out.println("personService in IOC"); 15 } else { 16 System.out.println("personService not in IOC"); 17 } 18 } 19 20 }
運行:
personService in IOC
2. 默認配置文件
通常情況下,Spring Boot 在啟動時會將 resources 目錄下的 application.properties 或 apllication.yml 作為其默認配置文件,我們可以在該配置文件中對項目進行配置。
Spring Boot 項目中可以存在多個 application.properties 或 apllication.yml。啟動時會掃描以下 5 個位置的 application.properties 或 apllication.yml 文件,並將它們作為 Spring boot 的默認配置文件。
(1) file:./config/
(2) file:./config/*/
(3) file:./
(4) classpath:/config/
(5) classpath:/
注:file: 指當前項目根目錄;classpath: 指當前項目的類路徑,即 resources 目錄。
以上所有位置的配置文件都會被加載,且它們優先級依次降低,序號越小優先級越高。其次,位於相同位置的 application.properties 的優先級高於 application.yml。
所有位置的文件都會被加載,高優先級配置會覆蓋低優先級配置,形成互補配置,即:
(1) 存在相同的配置內容時,高優先級的內容會覆蓋低優先級的內容;
(2) 存在不同的配置內容時,高優先級和低優先級的配置內容取並集;
示例,在 “ Springboot基礎知識(01)- Spring Boot 簡介、配置 Spring Boot 和 Spring Initializr ” 里 SpringbootBasic 項目基礎上,修改如下。
1) 創建 src/main/java/com/example/entity/User.java 文件
1 package com.example.entity; 2 3 import org.springframework.stereotype.Component; 4 import org.springframework.boot.context.properties.ConfigurationProperties; 5 6 @Component 7 @ConfigurationProperties(prefix = "user") 8 public class User { 9 private String username; 10 private Integer age; 11 12 public User() { 13 14 } 15 16 public String getUsername() { 17 return username; 18 } 19 public void setUsername(String username) { 20 this.username = username; 21 } 22 23 public Integer getAge() { 24 return age; 25 } 26 public void setAge(Integer age) { 27 this.age = age; 28 } 29 @Override 30 public String toString() { 31 return "User {" + 32 "username = " + username + 33 ", age = " + age + 34 '}'; 35 } 36 }
2) 在項目根目錄下創建 /application.yml 文件,配置如下。
user:
username: admin
age: 18
3) 在項目類路徑下(src/main/resources)創建 application.yml 文件,配置如下。
user:
username: admin2
age: 21
4) 在項目類路徑下的 config 目錄下 (src/main/resources/config) 創建 application.yml 文件,配置如下。
user:
username: admin3
age: 28
5) 創建 src/main/java/com/example/ApplicationContextUtils.java 文件
1 package com.example; 2 3 import org.springframework.beans.BeansException; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.ApplicationContextAware; 6 import org.springframework.stereotype.Component; 7 8 /* 9 * 在非 SpringBoot 工廠管理的普通類中,如果要獲取工廠管理的對象,不能再使用 @Autowired 等注入的注解, 10 * SpringBoot 提供了一個 “ApplicationContextAware” 接口,實現此接口,即可獲取工廠管理的全部內容。 11 */ 12 @Component 13 public class ApplicationContextUtils implements ApplicationContextAware { 14 private static ApplicationContext applicationContext; 15 16 @Override 17 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 18 this.applicationContext = applicationContext; 19 } 20 21 // 通過屬性名獲取對象 22 public static Object getById(String id){ 23 Object bean = applicationContext.getBean(id); 24 return bean; 25 } 26 27 // 通過屬性類獲取對象 28 public static Object getByClass(Class clazz){ 29 Object bean = applicationContext.getBean(clazz); 30 return bean; 31 } 32 33 // 通過屬性類獲取對象 34 public static Object getByNameAndClass(String id,Class clazz){ 35 Object bean = applicationContext.getBean(id,clazz); 36 return bean; 37 } 38 39 }
6) 修改 src/main/java/com/example/App.java 文件
1 package com.example; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6 import com.example.entity.User; 7 8 @SpringBootApplication 9 public class App { 10 11 public static void main(String[] args) { 12 SpringApplication.run(App.class, args); 13 14 User user = (User) ApplicationContextUtils.getById("user"); 15 System.out.println(user); 16 } 17 18 }
運行:
User {username = admin, age = 18}
注:對應項目根目錄下 application.yml 文件里的配置。
3. 外部配置文件
除了默認配置文件,Spring Boot 還可以加載一些位於項目外部的配置文件。我們可以通過如下 2 個參數,指定外部配置文件的路徑:
spring.config.location
spring.config.additional-location
1) spring.config.location
可以先將 Spring Boot 項目打包成 JAR 文件,然后在命令行啟動命令中,使用命令行參數 --spring.config.location,指定外部配置文件的路徑。
java -jar {JAR} --spring.config.location={外部配置文件全路徑}
需要注意的是,使用該參數指定配置文件后,會使項目默認配置文件(application.properties 或 application.yml )失效,Spring Boot 將只加載指定的外部配置文件。
示例,在上文修改過的 SpringbootBasic 項目基礎上,進行演示。
(1) 在本地目錄 D:\temp 下,創建一個配置文件 outer-application.yml,配置如下。
user:
username: admin-out
age: 32
(2) 打包 jar
打包操作參考 “ Springboot基礎知識(01)- Spring Boot 簡介、配置 Spring Boot 和 Spring Initializr ” 的 “2. 創建 Maven Quickstart 項目" 下的 “5)使用 spring-boot-maven-plugin 插件運行打包”。
(3) 運行 jar
點擊 IDEA 底部 Terminal 標簽頁,執行如下命令。
java -jar target/SpringbootBasic-1.0-SNAPSHOT.jar --spring.config.location=D:\temp\outer-application.yml
Terminal 輸出:
User {username = admin-out, age = 32}
2) spring.config.additional-location
還可以在 Spring Boot 啟動時,使用命令行參數 --spring.config.additional-location 來加載外部配置文件。
java -jar {JAR} --spring.config.additional-location={外部配置文件全路徑}
與 --spring.config.location 不同,--spring.config.additional-location 不會使項目默認的配置文件失效,使用該命令行參數添加的外部配置文件會與項目默認的配置文件共同生效,形成互補配置,且其優先級是最高的,比所有默認配置文件的優先級都高。
示例,在上文SpringbootBasic 項目基礎上,運行如下命令
java -jar target/SpringbootBasic-1.0-SNAPSHOT.jar --spring.config.additional-location=D:\temp\outer-application.yml
Terminal 輸出:
User {username = admin-out, age = 32}
3) IDEA Run/Debug Configuration 使用外部配置文件
(1) 虛擬機參數方式
Edit Configurations
Click "+" add new configuration -> Select "Application"
Name: SpringbootBasic
Main class: com.example.App
VM options: -Dspring.config.additional-location=D:\temp\outer-application.yml
-> Apply / OK
Click Run "SpringbootBasic"
User {username = admin-out, age = 32}
(2) 程序運行參數方式
Edit Configurations
Click "+" add new configuration -> Select "Application"
Name: SpringbootBasic
Main class: com.example.App
Program arguments: --spring.config.additional-location=D:\temp\outer-application.yml
-> Apply / OK
Click Run "SpringbootBasic"
User {username = admin-out, age = 32}
