SpringCloud之NamedContextFactory

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();// 可以为空,非必选项

	}

}

SpringCloud之NamedContextFactory_第1张图片

你可能感兴趣的:(spring,cloud,rpc,spring)