NamedContextFactory 可以创建一个子容器(或者说子上下文),每个子容器可以通过 Specification 定义 Bean。
public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
implements DisposableBean, ApplicationContextAware {
private final String propertySourceName;
private final String propertyName;
// 全部服务名对应IOC容器的缓存池:key为目标服务名,value为该服务名对应的应用上下文
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
// String为服务名,C 为内部接口Specification的子类。参考 FeignClientSpecification。
// 配置类集合:其key通常为目标服务名【@FeignClient注解的name属性】,value类型为FeignClientSpecification。如图所示
private Map<String, C> configurations = new ConcurrentHashMap<>();
private ApplicationContext parent;
//配置类:在配置类中可以自定义需要的bean,在合适时机利用自定义bean实现特需的功能。参考 FeignClientsConfiguration
private Class<?> defaultConfigType;
public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName, String propertyName) {
this.defaultConfigType = defaultConfigType;
this.propertySourceName = propertySourceName;
this.propertyName = propertyName;
}
public void setConfigurations(List<C> configurations) {
for (C client : configurations) {
this.configurations.put(client.getName(), client);
}
}
// name是指服务名【@FeignClient注解的name属性】。
//例如接口类型的Feign客户端在IOC容器中的bean类型为通过FactoryBean工厂类生成的代理类。
// 多个Feign客户端在实例化Bean的过程中都会执行以下方法。
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;// 创建当前服务名name对应的应用上下文或者容器
if (this.parent != null) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
...
context = new AnnotationConfigApplicationContext(beanFactory);
}else {
context = new AnnotationConfigApplicationContext();
}
if (this.configurations.containsKey(name)) {
// 调用 接口Specification实现类的 getConfiguration 获取配置类。参考 FeignClientSpecification。
//从 FeignClientSpecification 中获取Configuration。
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
// 将 Specification 中设置的配置类的BeanDefination信息添加到 当前服务名对应的应用上下文中
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);
}
}
}
// 在当前容器中创建PropertyPlaceholderAutoConfiguration、defaultConfigType类的BeanDefination
context.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
SingletonMap sm = Collections.<String, Object>singletonMap(this.propertyName, name);
MapPropertySource mps = new MapPropertySource(this.propertySourceName,sm);
context.getEnvironment().getPropertySources().addFirst(mps);
if (this.parent != null) {
context.setParent(this.parent);
}
context.setDisplayName(generateDisplayName(name));
context.refresh();// 刷新容器【创建BeanDefinations集合中BeanDefination对应的bean实例】
return context;
}
protected String generateDisplayName(String name) {
return this.getClass().getSimpleName() + "-" + name;
}
public <T> T getInstance(String name, Class<T> type) {
AnnotationConfigApplicationContext context = getContext(name);
return context.getBean(type);
}
...
public <T> T getInstance(String name, Class<?> clazz, Class<?>... generics) {
ResolvableType type = ResolvableType.forClassWithGenerics(clazz, generics);
return getInstance(name, type);
}
@SuppressWarnings("unchecked")
public <T> T getInstance(String name, ResolvableType type) {
AnnotationConfigApplicationContext context = getContext(name);
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type);
if (beanNames.length > 0) {
for (String beanName : beanNames) {
if (context.isTypeMatch(beanName, type)) {
return (T) context.getBean(beanName);
}
}
}
return null;
}
public <T> Map<String, T> getInstances(String name, Class<T> type) {
AnnotationConfigApplicationContext context = getContext(name);
return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);
}
public interface Specification {// 实现类可以参考FeignClientSpecification
String getName();
Class<?>[] getConfiguration();// 可以为空,非必选项
}
}