评论

收藏

[Java] SpringBoot 中 AutoConfiguration的使用方法

编程语言 编程语言 发布于:2021-08-17 11:57 | 阅读数:297 | 评论:0

在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;
  }
完整代码
https://github.com/lizu18xz/fim.git
总结
以上所述是小编给大家介绍的springboot 中 autoconfiguration的使用方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对CodeAE代码之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
原文链接:https://www.imooc.com/article/285008
关注下面的标签,发现更多相似文章