spring?NamedContextFactory在Fegin配置及使用詳解
引言
文中代碼來源于spring-cloud的2.2.9.release版本。
1、NamedContextFactory
看一下NamedContextFactory的主要代碼。NamedContextFactory中有個contexts屬性,contexts是Map<String, AnnotationConfigApplicationContext>,這個map以name為key 以子上線文為value。
getContext方法會從contexts查找name為key的子上下文,如果沒有的話會調(diào)用createContext創(chuàng)建一個子上下文。
createContext方法是NamedContextFactory的重要方法之一。
createContext首選創(chuàng)建一個AnnotationConfigApplicationContext作為子上下文;然后查詢configurations中有無以此name為key的Specification(這個類稍后介紹),如果有相關的Specification的話就會注冊這個
Specification存儲的class到子上下文;
然后注冊configurations中包含的以"defalut."開頭的key的Specification中存儲的class到子上下文;緊接著在子上下文注冊了PropertyPlaceholderAutoConfiguration 和 defaultConfigType(構造方法中初始的變量);
緊接著注冊了一個名字為propertySourceName的MapPropertySource,MapPropertySource的內(nèi)容包括一個key為propertyName值為name的變量;后邊進行設置parent然后refresh子上下文。
可以看到NamedContextFactory可以通過getContext(name)并為每個模塊構造不同的上下文,并且加載相關的配置加載到子上下文。
使用時可以通過Specification就是存儲了模塊名稱和每個模塊的配置類,進行配置,也可以通過NamedContextFactory指定一個配置類。
后邊的getInstance等方法,都是通過查詢子上下文中的來加載bean。
public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
implements DisposableBean, ApplicationContextAware {
private final String propertySourceName;
private final String propertyName;
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
private Map<String, C> configurations = new ConcurrentHashMap<>();
private Class<?> defaultConfigType;
public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName,
String propertyName) {
this.defaultConfigType = defaultConfigType;
this.propertySourceName = propertySourceName;
this.propertyName = propertyName;
}
protected AnnotationConfigApplicationContext getContext(String name) {
if (!this.contexts.containsKey(name)) {
synchronized (this.contexts) {
if (!this.contexts.containsKey(name)) {
this.contexts.put(name, createContext(name));
}
}
}
return this.contexts.get(name);
}
protected AnnotationConfigApplicationContext createContext(String name) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name)
.getConfiguration()) {
context.register(configuration);
}
}
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
context.register(configuration);
}
}
}
context.register(PropertyPlaceholderAutoConfiguration.class,
this.defaultConfigType);
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
this.propertySourceName,
Collections.<String, Object>singletonMap(this.propertyName, name)));
if (this.parent != null) {
// Uses Environment from parent as well as beans
context.setParent(this.parent);
// jdk11 issue
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
context.setClassLoader(this.parent.getClassLoader());
}
context.setDisplayName(generateDisplayName(name));
context.refresh();
return context;
}
public <T> T getInstance(String name, Class<T> type) {
AnnotationConfigApplicationContext context = getContext(name);
try {
return context.getBean(type);
}
catch (NoSuchBeanDefinitionException e) {
// ignore
}
return null;
}
public void setConfigurations(List<C> configurations) {
for (C client : configurations) {
this.configurations.put(client.getName(), client);
}
}
}public interface Specification {
String getName();
Class<?>[] getConfiguration();
}2、NamedContextFactory在feign中使用
feign中提供了Specification的實現(xiàn)
class FeignClientSpecification implements NamedContextFactory.Specification {
private String name;
private Class<?>[] configuration;
}EnableFeignClients中import了FeignClientsRegistrar,下面代碼不是全部的EnableFeignClients代碼,做了簡化處理。
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients中import了 {
Class<?>[] defaultConfiguration() default {};
}具體client的配置注冊是在FeignClientsRegistrar 實現(xiàn)的。registerBeanDefinitions方法實現(xiàn)了具體注冊。
registerDefaultConfiguration 將EnableFeignClients中的defaultConfiguration的配置,以"defalut."開頭的名稱注入到了容器。
registerFeignClients掃描所有的@FeignClient類,得到name(具體邏輯可參考源碼),得到FeignClient的configration屬性,再調(diào)用registerClientConfiguration 就行配置(注冊了name + "." + FeignClientSpecification.class.getSimpleName()的bean)。
class FeignClientsRegistrar
implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
Object configuration) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientSpecification.class);
builder.addConstructorArgValue(name);
builder.addConstructorArgValue(configuration);
registry.registerBeanDefinition(
name + "." + FeignClientSpecification.class.getSimpleName(),
builder.getBeanDefinition());
}
}在FeignAutoConfiguration中引入了所有的 FeignClientSpecification,并且初始化了FeiginContext,調(diào)用了setConfigurations(參考NamedContextFactory方法,此操作將以name為key,F(xiàn)eignClientSpecification對象為value添加到NamedContextFactory的configurations屬性中),后續(xù)在調(diào)用到NamedContextFactory的createContext方法時,會將configurations屬性中的配置進行加載。
public class FeignAutoConfiguration {
@Autowired(required = false)
private List<FeignClientSpecification> configurations = new ArrayList<>();
@Bean
public FeignContext feignContext() {
FeignContext context = new FeignContext();
context.setConfigurations(this.configurations);
return context;
}
}以上就是spring NamedContextFactory在Fegin配置及使用詳解的詳細內(nèi)容,更多關于spring NamedContextFactory Fegin配置的資料請關注腳本之家其它相關文章!
相關文章
Java使用@Autowired注解獲取對象為null的幾種情況及解決方法
這篇文章主要給大家介紹了使用@Autowired注解獲取對象為null的幾種情況以及?解決方法,文中有詳細的代碼示例講解,具有一定的參考價值,需要的朋友可以參考下2023-09-09
解決idea中javaweb的mysql8.0.15配置問題
這篇文章主要介紹了idea中javaweb的mysql8.0.15配置問題 ,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05
服務器實現(xiàn)Java遠程訪問Linux服務器方式(JSch)
文章介紹了如何使用Java遠程訪問Linux服務器,主要包括建立SSH連接、使用JSch庫執(zhí)行命令、解析返回值以及關閉連接的步驟2024-11-11

