SpringBoot 中 AutoConfiguration的使用方法

网友投稿 482 2023-01-08


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 configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {

List 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 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 URLRegishttp://try {

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 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呢

首先要在需要使用的项目中引入依赖

com.fayayo

fim-registry-zookeeper

0.0.1-SNAPSHOT

然后配置参数

fim:

register:

address: 192.168.88.129:2181

timeout: 2000

如果不配置会有默认的参数

具体使用的时候只需要在Bean中注入就可以了,比如

@Autowired

private Registry registry;

public List getAll(){

Listlist=cache.get(KEY);

if(CollectionUtils.isEmpty(list)){

list=registry.discover();

cache.put(KEY,list);

}

return list;

}

完整代码

https://github.com/lizu18xz/fim.git

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:自动化接口测试造数(接口自动化测试怎么做)
下一篇:微服务网关业务聚合(微服务网关zuul)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~