SpringBoot 中 AutoConfiguration的使用方法
在springboot中我们经常可以引入一些starter包来集成一些工具的使用,比如spring-boot-starter-data-redis
。
使用起来很方便,那么是如何实现的呢?
代码分析
我们先看注解@springbootapplication
,它里面包含一个@enableautoconfiguration
继续看@enableautoconfiguration注解
@import({autoconfigurationimportselector.class})
在这个类(autoconfigurationimportselector)里面实现了自动配置的加载
主要代码片段:
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; }
最后会通过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
我们来实现一个zk的autoconfiguration
首先定义一个zookeeperautoconfiguration类
然后在meta-inf/spring.factories中加入
org.springframework.boot.autoconfigure.enableautoconfiguration=com.fayayo.fim.zookeeper.zookeeperautoconfiguration
接下来我们看看具体的实现:
@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部分实现:
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); } //监听 zkclient.subscribechildchanges(parentpath, new izkchildlistener() { //对父节点添加监听子节点变化。 @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"); } }
具体使用
那么我们怎么使用自己写的zookeeperautoconfiguration呢
首先要在需要使用的项目中引入依赖
<dependency> <groupid>com.fayayo</groupid> <artifactid>fim-registry-zookeeper</artifactid> <version>0.0.1-snapshot</version> </dependency>
然后配置参数
fim: register: address: 192.168.88.129:2181 timeout: 2000
如果不配置会有默认的参数
具体使用的时候只需要在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; }
完整代码
总结
以上所述是小编给大家介绍的springboot 中 autoconfiguration的使用方法,希望对大家有所帮助