首页 > 编程 > Java > 正文

SpringBoot 中 AutoConfiguration的使用方法

2019-11-26 09:05:33
字体:
来源:转载
供稿:网友

在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")@Configurationpublic 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)@Slf4jpublic 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的使用方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表