在開發過程中,我們需要根據不同的應用場景添加不同的模塊,比如jdbc操作,我們除了添加基礎的接口模塊外,還需要根據不同的數據庫添加針對該數據庫的模塊,在這樣的場景下,就需要用到自動配置模塊。
實現一個簡單的自動配置模塊的步驟:
1.構建一個配置類,用於讀取配置文件
本例子直接讀取application.properties,若有自定義的配置文件,可以單獨進行配置
@ConfigurationProperties(prefix = "custom")
public class AuthorProperties {
private static final String DEFAULT_AUTHOR = "Hello World";
private String author = DEFAULT_AUTHOR;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
2.構建一個服務類,用於提供服務
本例子服務類實現了讀取配置文件中的信息
public class AuthorServer {
private String author;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
3.構建自動配置類
springboot在啓動的時候,會讀取spring.factories文件,自動實例化該類並加入到spring容器中
@Configuration
/**
* springboot通過判斷是否有AuthorServer這個類,來判斷該Configuration是否有效
* 若有AuthorServer這個類,則Configuration有效
* 若無AuthorServer這個類,則Configuration無效
*/
@ConditionalOnClass({AuthorServer.class})
/**
* @EnableConfigurationProperties 註解的作用是使配置了@ConfigurationProperties 註解的類生效
* 1.一個配置類只配置了@ConfigurationProperties,而沒有配置@Component,那麼spring容器中無法獲取配置類,即沒有實例化
* 配置了@ConfigurationProperties的類
* 2.@EnableConfigurationProperties 相當於將只配置了@ConfigurationProperties的配置類進行了一次注入
*/
@EnableConfigurationProperties(AuthorProperties.class)
public class AuthorAutoConfiguration {
@Autowired
private AuthorProperties authorProperties;
@Bean(name = "authorServer")
/**
* springboot通過@ConditionalOnProperty來判斷@Bean是否有效
* 通過name和havingValue來實現,其中name表示從application.properties中讀取的key
* 1.若application.properties中不存在custom.author.enable,若matchIfMissing = true,則@Bean有效
* 2.若application.properties中custom.author.enable有值,將該值與havingValue進行比較
* ①若custom.author.enable的值與havingValue的值一樣,則返回true,@Bean有效
* ①若custom.author.enable的值與havingValue的值不一樣,則返回false,@Bean無效
*/
@ConditionalOnProperty(name = "custom.author.enable", havingValue = "true", matchIfMissing = true)
public AuthorServer authorServer() {
AuthorServer authorServer = new AuthorServer();
authorServer.setAuthor(authorProperties.getAuthor());
return authorServer;
}
@Bean(name = "authorServer")
/**
* 當spring容器中存在AuthorServer實例時,不進行下述方法的實例化
* 當spring容器中不存在AuthorServer實例時,進行下述方法的實例化
*/
@ConditionalOnMissingBean(AuthorServer.class)
public AuthorServer authorServerDefault() {
AuthorServer authorServer = new AuthorServer();
authorServer.setAuthor("default name");
return authorServer;
}
}
4.不要忘記spring.factories文件,springboot根據該文件的內容,決定哪些類需要實例化,並且加入到spring容器中
在resources目錄下創建META-INF目錄,然後創建spring.factories文件
spring.factories文件內容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.navinfo.had.factories.AuthorAutoConfiguration
5.將該工程打成一個jar包,用於其他工程引用
<dependency> <groupId>com.navinfo.springcloud</groupId> <artifactId>spring-cloud-factories</artifactId> <version>0.0.1</version> </dependency>
6.測試:
application.properties如下:
custom.author=aaa
custom.author.enable=false
@RunWith(SpringRunner.class)
@SpringBootTest
public class FactoriesTest {
@SpringBootApplication(scanBasePackages = "com.test")
static class InnerConfig { }
@Autowired
private AuthorServer authorServer;
@Test
public void test() {
System.out.println(authorServer.getAuthor());
}
}
返回結果:
1.當custom.author.enable不存在時,打印aaa
2.當custom.author.enable=true,打印aaa
3.當custom.author.enable=false,打印default name
思維發散:
在開發工程中,我們會針對類似的場景,開發不同的模塊,比如ORM框架,我們會開發oracle模塊,mysql模塊,postgres模塊等等,當我們引入其中一個模塊後,如何進行註冊,當取消一個模塊後,如何進行剔除