SpringBoot 中 AutoConfiguration的使用方法
在SpringBoot中我們經(jīng)??梢砸胍恍﹕tarter包來(lái)集成一些工具的使用,比如spring-boot-starter-data-redis。
使用起來(lái)很方便,那么是如何實(shí)現(xiàn)的呢?
代碼分析
我們先看注解@SpringBootApplication,它里面包含一個(gè)@EnableAutoConfiguration
繼續(xù)看@EnableAutoConfiguration注解
@Import({AutoConfigurationImportSelector.class})
在這個(gè)類(AutoConfigurationImportSelector)里面實(shí)現(xiàn)了自動(dòng)配置的加載
主要代碼片段:
String[] selectImports(AnnotationMetadata annotationMetadata)方法中
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
getAutoConfigurationEntry方法中:
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
最后會(huì)通過(guò)SpringFactoriesLoader.loadSpringFactories去加載META-INF/spring.factories
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryClassName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryName = var9[var11];
result.add(factoryClassName, factoryName.trim());
}
}
}
ZookeeperAutoConfiguration
我們來(lái)實(shí)現(xiàn)一個(gè)ZK的AutoConfiguration
首先定義一個(gè)ZookeeperAutoConfiguration類
然后在META-INF/spring.factories中加入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.fayayo.fim.zookeeper.ZookeeperAutoConfiguration
接下來(lái)我們看看具體的實(shí)現(xiàn):
@ConfigurationProperties(prefix = "fim.register")
@Configuration
public class URLRegistry {
private String address;
private int timeout;
private int sessionTimeout;
public String getAddress() {
if (address == null) {
address = URLParam.ADDRESS;
}
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getTimeout() {
if (timeout == 0) {
timeout = URLParam.CONNECTTIMEOUT;
}
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getSessionTimeout() {
if (sessionTimeout == 0) {
sessionTimeout = URLParam.REGISTRYSESSIONTIMEOUT;
}
return sessionTimeout;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
}
@Configuration
@EnableConfigurationProperties(URLRegistry.class)
@Slf4j
public class ZookeeperAutoConfiguration {
@Autowired
private URLRegistry url;
@Bean(value = "registry")
public Registry createRegistry() {
try {
String address = url.getAddress();
int timeout = url.getTimeout();
int sessionTimeout = url.getSessionTimeout();
log.info("init ZookeeperRegistry,address[{}],sessionTimeout[{}],timeout[{}]", address, timeout, sessionTimeout);
ZkClient zkClient = new ZkClient(address, sessionTimeout, timeout);
return new ZookeeperRegistry(zkClient);
} catch (ZkException e) {
log.error("[ZookeeperRegistry] fail to connect zookeeper, cause: " + e.getMessage());
throw e;
}
}
}
ZookeeperRegistry部分實(shí)現(xiàn):
public ZookeeperRegistry(ZkClient zkClient) {
this.zkClient = zkClient;
log.info("zk register success!");
String parentPath = URLParam.ZOOKEEPER_REGISTRY_NAMESPACE;
try {
if (!zkClient.exists(parentPath)) {
log.info("init zookeeper registry namespace");
zkClient.createPersistent(parentPath, true);
}
//監(jiān)聽
zkClient.subscribeChildChanges(parentPath, new IZkChildListener() {
//對(duì)父節(jié)點(diǎn)添加監(jiān)聽子節(jié)點(diǎn)變化。
@Override
public void handleChildChange(String parentPath, List<String> currentChilds) {
log.info(String.format("[ZookeeperRegistry] service list change: path=%s, currentChilds=%s", parentPath, currentChilds.toString()));
if(watchNotify!=null){
watchNotify.notify(nodeChildsToUrls(currentChilds));
}
}
});
ShutDownHook.registerShutdownHook(this);
} catch (Exception e) {
e.printStackTrace();
log.error("Failed to subscribe zookeeper");
}
}
具體使用
那么我們?cè)趺词褂米约簩懙腪ookeeperAutoConfiguration呢
首先要在需要使用的項(xiàng)目中引入依賴
<dependency>
<groupId>com.fayayo</groupId>
<artifactId>fim-registry-zookeeper</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
然后配置參數(shù)
fim:
register:
address: 192.168.88.129:2181
timeout: 2000
如果不配置會(huì)有默認(rèn)的參數(shù)
具體使用的時(shí)候只需要在Bean中注入就可以了,比如
@Autowired
private Registry registry;
public List<URL> getAll(){
List<URL>list=cache.get(KEY);
if(CollectionUtils.isEmpty(list)){
list=registry.discover();
cache.put(KEY,list);
}
return list;
}
完整代碼
https://github.com/lizu18xz/fim.git
總結(jié)
以上所述是小編給大家介紹的SpringBoot 中 AutoConfiguration的使用方法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
Java內(nèi)存模型之happens-before概念詳解
happens-before原則非常重要,它是判斷數(shù)據(jù)是否存在競(jìng)爭(zhēng)、線程是否安全的主要依據(jù),依靠這個(gè)原則,我們解決在并發(fā)環(huán)境下兩操作之間是否可能存在沖突的所有問題。下面我們就一個(gè)簡(jiǎn)單的例子稍微了解下happens-before知識(shí),感興趣的朋友一起看看吧2021-06-06
MyBatis游標(biāo)Cursor的正確使用和百萬(wàn)數(shù)據(jù)傳輸?shù)膬?nèi)存測(cè)試
這篇文章主要介紹了MyBatis游標(biāo)Cursor的正確使用和百萬(wàn)數(shù)據(jù)傳輸?shù)膬?nèi)存測(cè)試,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件 FTP軟件遠(yuǎn)程窗口實(shí)現(xiàn)(6)
這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件,F(xiàn)TP軟件遠(yuǎn)程窗口的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
springboot 接收List 入?yún)⒌膸追N方法
本文主要介紹了springboot 接收List 入?yún)⒌膸追N方法,本文主要介紹了7種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03
Java利用Dijkstra和Floyd分別求取圖的最短路徑
本文主要介紹了圖的最短路徑的概念,并分別利用Dijkstra算法和Floyd算法求取最短路徑,最后提供了基于鄰接矩陣和鄰接表的圖對(duì)兩種算法的Java實(shí)現(xiàn)。需要的可以參考一下2022-01-01
IO流概述分類字節(jié)流寫數(shù)據(jù)三種方式及問題分析
這篇文章主要為大家介紹了IO流概述分類字節(jié)流寫數(shù)據(jù)三種方式及寫數(shù)據(jù)問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
springboot themaleaf 第一次進(jìn)頁(yè)面不加載css的問題
這篇文章主要介紹了springboot themaleaf 第一次進(jìn)頁(yè)面不加載css的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10

