1、Spring配置歷史
事實上,在Spring3.0開始,Spring官方就已經開始推薦使用java配置來代替傳統的xml配置了,我們不妨來回顧一下
Spring的歷史:
Spring1.0時代,在此時因爲jdk1.5剛剛出來,註解開發並未盛行,因此一切Spring配置都是xml格式,想象一下所有的bean都用xml配置,細思極恐啊,心疼那個時候的程序員2秒
Spring2.0時代,Spring引入了註解開發,但是因爲並不完善,因此並未完全替代xml,此時的程序員往往是把xml與註解進行結合,貌似我們之前都是這種方式。
Spring3.0及以後,3.0以後Spring的註解已經非常完善了,因此Spring推薦大家使用完全的java配置來代替以前的xml,不過似乎在國內並未推廣盛行。然後當Spring Boot來臨,人們才慢慢認識到java配置的優雅。
2、嘗試java配置
2.1、配置類方式
以前配置數據源是通過xml文件實現的,例如:
現在通過定義配置類:
數據庫配置:
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://47.100.229.xxx:3306/springStudy?useSSL=false&serverTimezone=UTC jdbc.username=root jdbc.password=xxxx jdbc.initialSize=1 jdbc.minIdle=3 jdbc.maxActive=20 jdbc.maxWait=60000
配置類代碼:
package rui.config; import com.alibaba.druid.pool.DruidDataSource; import jdk.nashorn.internal.objects.annotations.Property; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import javax.sql.DataSource; /*數據庫配置類*/ @Configuration @PropertySource("classpath:jdbc.properties") public class JdbcConfig { @Value("${jdbc.driverClassName}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Value("${jdbc.initialSize}") private int initialSize; @Value("${jdbc.minIdle}") private int minIdle; @Value("${jdbc.maxActive}") private int maxActive; @Value("${jdbc.maxWait}") private int maxWait; @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); dataSource.setInitialSize(initialSize); dataSource.setMinIdle(minIdle); dataSource.setMaxActive(maxActive); dataSource.setMaxWait(maxWait); return dataSource; } }
在控制器中注入數據源,調試即可查看是否注入相關的屬性值
@RestController @RequestMapping(value = "hello") public class HelloController { @Autowired private DataSource dataSource; @RequestMapping(value = "index") public String hello() { System.out.println(dataSource.toString()); return "index"; } }
2.2、屬性方式
屬性讀取類
package rui.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "jdbc") public class JdbcProperties { private String driverClassName; private String url; private String username; private String password; private int initialSize; private int minIdle; private int maxActive; private int maxWait; public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driver) { this.driverClassName = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getInitialSize() { return initialSize; } public void setInitialSize(int initialSize) { this.initialSize = initialSize; } public int getMinIdle() { return minIdle; } public void setMinIdle(int minIdle) { this.minIdle = minIdle; } public int getMaxActive() { return maxActive; } public void setMaxActive(int maxActive) { this.maxActive = maxActive; } public int getMaxWait() { return maxWait; } public void setMaxWait(int maxWait) { this.maxWait = maxWait; } }
配置類代碼,現在不需要通過@value去讀取每一個配置項目。
package rui.config; import com.alibaba.druid.pool.DruidDataSource; import jdk.nashorn.internal.objects.annotations.Property; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import javax.sql.DataSource; /*數據庫配置類*/ @Configuration @EnableConfigurationProperties(JdbcProperties.class) public class JdbcConfig { @Bean public DataSource dataSource(JdbcProperties jdbcProperties) { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(jdbcProperties.getDriverClassName()); dataSource.setUrl(jdbcProperties.getUrl()); dataSource.setUsername(jdbcProperties.getUsername()); dataSource.setPassword(jdbcProperties.getPassword()); dataSource.setInitialSize(jdbcProperties.getInitialSize()); dataSource.setMinIdle(jdbcProperties.getMinIdle()); dataSource.setMaxActive(jdbcProperties.getMaxActive()); dataSource.setMaxWait(jdbcProperties.getMaxWait()); return dataSource; } }
2.3、更優雅的注入
@Configuration public class JdbcConfig { @Bean @ConfigurationProperties(prefix = "jdbc") public DataSource dataSource() { return new DruidDataSource(); } }
3、Yaml配置文件
3.1、多個yaml文件
當一個項目中有多個yml配置文件的時候,可以以application-**.yml命名;在application.yml中配置項目使用激活這些配置文件即可。
4、自動配置原理
使用Spring Boot之後,一個整合了SpringMVC的WEB工程開發,變的無比簡單,那些繁雜的配置都消失不見了,這是如何做到的?一切魔力的開始,都是從我們的main函數來的,所以我們再次來看下啓動類:
我們發現類上邊有註解:@SpringBootApplication,進入源碼查看:
通過這段我們可以看出,在這個註解上面,又有一個 @Configuration 註解。通過上面的註釋閱讀我們知道:這個註解的作用就是聲明當前類是一個配置類,然後Spring會自動掃描到添加了 @Configuration 的類,並且讀取其中的配置信息。而 @SpringBootConfiguration 是來聲明當前類是SpringBoot應用的配置類,項目中只能有一個。所以一般我們無需自己添加。
第二級的註解 @EnableAutoConfiguration ,告訴Spring Boot基於你所添加的依賴,去“猜測”你想要如何配置Spring。比如我們引入了 spring-boot-starter-web ,而這個啓動器中幫我們添加了 tomcat 、 SpringMVC的依賴。此時自動配置就知道你是要開發一個web應用,所以就幫你完成了web及SpringMVC的默認配置了!
所以,我們使用SpringBoot構建一個項目,只需要引入所需框架的依賴,配置就可以交給SpringBoot處理了。除非你不希望使用SpringBoot的默認配置,它也提供了自定義配置的入口。
@ComponentScan
配置組件掃描的指令。提供了類似與 <context:component-scan> 標籤的作用通過basePackageClasses或者basePackages屬性來指定要掃描的包。如果沒有指定這些屬性,那麼將從聲明這個註解的類所在的包開始,掃描包及子包
而我們的@SpringBootApplication註解聲明的類就是main函數所在的啓動類,因此掃描的包是該類所在包及其子包。因此,一般啓動類會放在一個比較前的包目錄中。
5、自動配置修改方案
SpringBoot爲我們提供了默認配置,而默認配置生效的步驟:
- @EnableAutoConfiguration註解會去尋找 META-INF/spring.factories 文件,讀取其中以
- EnableAutoConfiguration 爲key的所有類的名稱,這些類就是提前寫好的自動配置類
- 這些類都聲明瞭 @Configuration 註解,並且通過 @Bean 註解提前配置了我們所需要的一切實例
- 但是,這些配置不一定生效,因爲有 @ConditionalOn 註解,滿足一定條件纔會生效。比如條件之一: 是一些 相關的類要存在
- 類要存在,我們只需要引入了相關依賴(啓動器),依賴有了條件成立,自動配置生效。
- 如果我們自己配置了相關Bean,那麼會覆蓋默認的自動配置的Bean
- 我們還可以通過配置application.yml文件,來覆蓋自動配置中的屬性
1)啓動器
所以,我們如果不想配置,只需要引入依賴即可,而依賴版本我們也不用操心,因爲只要引入了SpringBoot提供的starter(啓動器),就會自動管理依賴及版本了。因此,玩SpringBoot的第一件事情,就是找啓動器,SpringBoot提供了大量的默認啓動器
2)全局配置
另外,SpringBoot的默認配置,都會讀取默認屬性,而這些屬性可以通過自定義 application.properties 文件來進行覆蓋。這樣雖然使用的還是默認配置,但是配置中的值改成了我們自定義的。因此,玩SpringBoot的第二件事情,就是通過 application.properties 來覆蓋默認屬性值,形成自定義配置。我們需要知道SpringBoot的默認屬性key,非常多,可以再idea中自動提示
默認配置的組件很多:
6、自動配置修改例子