BeanDefinition是对一个bean的描述,包括bean的各种信息,比如bean的类型、bean的属性、scope是单例还是原型、是否懒加载、init方法、destory方法等。博主这样理解,用@Bean注解定义一个bean时,bean的各种属性通常都是常量,BeanDefinition类的作用就是可以动态的去定义bean。
DefaultListableBeanFactory类是Spring的核心类,有获取bean的各种方法。该类BeanDefinition的关联就是维护一个ConcurrentHashMap,key为beanName,value为BeanDefinition。该类中registerBeanDefinition的方法就是往ConcurrentHashMap里put一个值,这个过程称为bean的注册。该类的职责就是对所有bean的管理以及实例化。
在Spring Boot应用中要启用Feign,要在SpringBootApplication类上面加上@EnableFeignClients注解。查看@EnableFeignClients注解源码,相比其他的普通注解多了一行@Import({FeignClientsRegistrar.class})。FeignClientsRegistrar类的对象也会被Spring容器管理。
package org.springframework.cloud.openfeign;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
String[] value() default {};
String[] basePackages() default {};
Class>[] basePackageClasses() default {};
Class>[] defaultConfiguration() default {};
Class>[] clients() default {};
}
FeignClientsRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以registerBeanDefinitions方法在应用启动时就执行。
package org.springframework.cloud.openfeign;
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private Environment environment;
...
//应用启动时执行
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerDefaultConfiguration(metadata, registry);
this.registerFeignClients(metadata, registry);
}
//将@EnableFeignClients注解里的defaultConfiguration配置
private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
Map defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
//如果EnableFeignClients.defaultConfiguration,则会执行
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
String name;
if (metadata.hasEnclosingClass()) {
name = "default." + metadata.getEnclosingClassName();
} else {
name = "default." + metadata.getClassName();
}
this.registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration"));
}
}
//注册FeignClient
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//获取扫描器
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);
//获取@EnableFeignClients注解上的配置
Map attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
Class>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
Object basePackages;
if (clients != null && clients.length != 0) {
//如果@EnableFeignClients注解上的配置指定了clients
final Set clientClasses = new HashSet();
basePackages = new HashSet();
Class[] var9 = clients;
int var10 = clients.length;
for(int var11 = 0; var11 < var10; ++var11) {
Class> clazz = var9[var11];
//所有指定的clients的包路径都需要扫描
((Set)basePackages).add(ClassUtils.getPackageName(clazz));
clientClasses.add(clazz.getCanonicalName());
}
AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
protected boolean match(ClassMetadata metadata) {
String cleaned = metadata.getClassName().replaceAll("\\$", ".");
return clientClasses.contains(cleaned);
}
};
scanner.addIncludeFilter(new FeignClientsRegistrar.AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
} else {
//如果@EnableFeignClients注解上的配置未指定clients,则扫描SpringBootApplication类的包以及子路径,并且是加了@FeignClient注解的类
scanner.addIncludeFilter(annotationTypeFilter);
basePackages = this.getBasePackages(metadata);
}
Iterator var17 = ((Set)basePackages).iterator();
while(var17.hasNext()) {
String basePackage = (String)var17.next();
Set candidateComponents = scanner.findCandidateComponents(basePackage);
Iterator var21 = candidateComponents.iterator();
while(var21.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var21.next();
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
//获取扫描到的类@FeignClient注解的配置
Map attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String name = this.getClientName(attributes);
//注册单个FeignClient的配置
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
//注册单个@FeignClient类的定义
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map attributes) {
String className = annotationMetadata.getClassName();
//所有FeignClient的bean的类型指为FeignClientFactoryBean类型
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
this.validate(attributes);
//设置FeignClient的各种属性
//获取@FeignClient配置的url 用于非微服务的请求url
definition.addPropertyValue("url", this.getUrl(attributes));
definition.addPropertyValue("path", this.getPath(attributes));
//获取@FeignClient配置的name 微服务服务名的转发
String name = this.getName(attributes);
definition.addPropertyValue("name", name);
String contextId = this.getContextId(attributes);
definition.addPropertyValue("contextId", contextId);
definition.addPropertyValue("type", className);
//获取@FeignClient配置的name 用于请求状态码返回404情况下对response的编码转换
definition.addPropertyValue("decode404", attributes.get("decode404"));
//获取@FeignClient配置的fallback 用于指定改FeignClient的熔断类
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(2);
String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
boolean primary = (Boolean)attributes.get("primary");
beanDefinition.setPrimary(primary);
String qualifier = this.getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
//注册FeignClient,将FeignClient的bean以及beanDefinition注册至DefaultListableBeanFactory,在实例化bean时如果bean的类型是FactoryBean则会继续调用FactoryBean的getObject方法生成bean
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
//完成FeignClientSpecification bean的注册,该bean的类型是FeignClientSpecification是一个普通类型,则在bean实例化的时候,就会调用该类的构造方法生成实例
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
//注册FeignClientSpecification bean
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
//添加构造参数
builder.addConstructorArgValue(name);
builder.addConstructorArgValue(configuration);
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition());
}
...
}
FeignClientsRegistrar类的主要职责是
(1)获取FeignClient bean并为其指定生成对象的类FeignClientFactoryBean,同时设置一些请求地址、服务名、以及相关配置。
(2)将@EnableFeignClients默认的Fegin配置以及@FeignClient的配置都以bean的方式初始化成FeignClientSpecification。
FeignContext是一个Bean,只将FeignClientSpecification类型的所有bean注入为属性。
package org.springframework.cloud.openfeign;
@Configuration
@ConditionalOnClass({Feign.class})
@EnableConfigurationProperties({FeignClientProperties.class, FeignHttpClientProperties.class})
public class FeignAutoConfiguration {
@Autowired(
required = false
)
private List configurations = new ArrayList();
public FeignAutoConfiguration() {
}
...
@Bean
public FeignContext feignContext() {
FeignContext context = new FeignContext();
context.setConfigurations(this.configurations);
return context;
}
}
FeignContext继承了NamedContextFactory类,通过这种方式把初始化的FeignClientSpecification以FeignClient的name分隔从而生成一个包含所有FeignClient配置的FeignContext bean。
package org.springframework.cloud.openfeign;
public class FeignContext extends NamedContextFactory {
public FeignContext() {
super(FeignClientsConfiguration.class, "feign", "feign.client.name");
}
}
package org.springframework.cloud.context.named;
public abstract class NamedContextFactory implements DisposableBean, ApplicationContextAware {
//通过一个name将上下文隔离
private Map contexts = new ConcurrentHashMap();
private Map configurations = new ConcurrentHashMap();
...
public void setConfigurations(List configurations) {
Iterator var2 = configurations.iterator();
while(var2.hasNext()) {
C client = (NamedContextFactory.Specification)var2.next();
//结合FeignClientSpecification的代码,猜到FeignContext的key就是FeignClient的name
this.configurations.put(client.getName(), client);
}
}
//获取实例的时候,也先通过name获取响应的上下文
public T getInstance(String name, Class type) {
AnnotationConfigApplicationContext context = this.getContext(name);
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0 ? context.getBean(type) : null;
}
...
public interface Specification {
String getName();
Class>[] getConfiguration();
}
}
FeignClientFactoryBean的getObject方法生成实例。
package org.springframework.cloud.openfeign;
class FeignClientFactoryBean implements FactoryBean
class DefaultFeignLoadBalancedConfiguration {
DefaultFeignLoadBalancedConfiguration() {
}
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
return new LoadBalancerFeignClient(new Default((SSLSocketFactory)null, (HostnameVerifier)null), cachingFactory, clientFactory);
}
}
public class FeignAutoConfiguration {
...
@Configuration
@ConditionalOnMissingClass({"feign.hystrix.HystrixFeign"})
protected static class DefaultFeignTargeterConfiguration {
protected DefaultFeignTargeterConfiguration() {
}
//如果没有HystrixFeign类,则Targeter bean就是DefaultTargeter
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
}
...
@Configuration
@ConditionalOnClass(
name = {"feign.hystrix.HystrixFeign"}
)
protected static class HystrixFeignTargeterConfiguration {
protected HystrixFeignTargeterConfiguration() {
}
//如果HystrixFeign类,则Targeter bean就是HystrixTargeter
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new HystrixTargeter();
}
}
}
@Configuration
public class FeignClientsConfiguration {
@Configuration
@ConditionalOnClass({HystrixCommand.class, HystrixFeign.class})
protected static class HystrixFeignConfiguration {
protected HystrixFeignConfiguration() {
}
//如果feign.hystrix.enabled不是true,则FeignClientFactoryBean里获取的builder就是Feign.builder 而不是HystrixFeign.Builder
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@ConditionalOnProperty(
name = {"feign.hystrix.enabled"}
)
public Builder feignHystrixBuilder() {
return HystrixFeign.builder();
}
}
}
如果feign.hystrix.enabled不是true,则FeignClientFactoryBean里获取的builder就是Feign.builder 而不是HystrixFeign.Builder
class HystrixTargeter implements Targeter {
HystrixTargeter() {
}
public T target(FeignClientFactoryBean factory, Builder feign, FeignContext context, HardCodedTarget target) {
//根据Builder的类型判断是否需要熔断
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
return feign.target(target);
} else {
feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder)feign;
SetterFactory setterFactory = (SetterFactory)this.getOptional(factory.getName(), context, SetterFactory.class);
if (setterFactory != null) {
builder.setterFactory(setterFactory);
}
Class> fallback = factory.getFallback();
if (fallback != Void.TYPE) {
return this.targetWithFallback(factory.getName(), context, target, builder, fallback);
} else {
Class> fallbackFactory = factory.getFallbackFactory();
return fallbackFactory != Void.TYPE ? this.targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory) : feign.target(target);
}
}
}
以上都是获取各种配置以及根据是否开启熔断获取一个Builder。
package feign;
public abstract class Feign {
public Feign() {
}
...
public static class Builder {
...
public T target(Target target) {
return this.build().newInstance(target);
}
public Feign build() {
//new一个 InvocationHandlerFactory
Factory synchronousMethodHandlerFactory = new Factory(this.client, this.retryer, this.requestInterceptors, this.logger, this.logLevel, this.decode404, this.closeAfterDecode, this.propagationPolicy);
//new一个Feign解析的处理器
ParseHandlersByName handlersByName = new ParseHandlersByName(this.contract, this.options, this.encoder, this.decoder, this.queryMapEncoder, this.errorDecoder, synchronousMethodHandlerFactory);
//生成ReflectiveFeign对象
return new ReflectiveFeign(handlersByName, this.invocationHandlerFactory, this.queryMapEncoder);
}
}
}
package feign;
public class ReflectiveFeign extends Feign {
private final ReflectiveFeign.ParseHandlersByName targetToHandlersByName;
private final InvocationHandlerFactory factory;
private final QueryMapEncoder queryMapEncoder;
ReflectiveFeign(ReflectiveFeign.ParseHandlersByName targetToHandlersByName, InvocationHandlerFactory factory, QueryMapEncoder queryMapEncoder) {
this.targetToHandlersByName = targetToHandlersByName;
this.factory = factory;
this.queryMapEncoder = queryMapEncoder;
}
public T newInstance(Target target) {
//通过HardCodedTarget里的type以及Contract里的协议解析成key为MethodHandler的configKey 由类型+方法名+参数类型组成 value为MethodHandler
Map nameToHandler = this.targetToHandlersByName.apply(target);
//判断并过滤转换成key为Method value为MethodHandler的的类型
Map methodToHandler = new LinkedHashMap();
List defaultMethodHandlers = new LinkedList();
Method[] var5 = target.type().getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method method = var5[var7];
if (method.getDeclaringClass() != Object.class) {
if (Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
methodToHandler.put(method, (MethodHandler)nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
}
//转换成InvocationHandler target指定类型,Map根据方法分发
InvocationHandler handler = this.factory.create(target, methodToHandler);
//生成代理对象
T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
Iterator var12 = defaultMethodHandlers.iterator();
while(var12.hasNext()) {
DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
...
}
待补充
FeignClient初始化过程如下:
(1)由FeignClientsRegistrar选择FeignClient,将FeignClient bean的类型通过BeanDefinition指定为FeignClientFactoryBean,并注册到DefaultListableBeanFactory由其管理。
(2)因为FeignClientFactoryBean实现了FactoryBean
(3)通过FeignContext获取不同的FeignClient的配置以及是否开启熔断生成Feign.builder(HystrixFeign.Builder继承了Feign.Builder)。
(4)Feign.Builder创建调用处理器工厂InvocationHandlerFactory、语法解析ParseHandlersByName对象生成ReflectiveFeign对象。
(5)ReflectiveFeign类newInstance方法,将FeignClient的类通过contract解析成MethodHandler,再由InvocationHandlerFactory生成FeignInvocationHandler对象,再生成代理对象。
其他:
(1)可以通过BeanDefinition动态注册bean。
(2)集成NamedContextFactory可以通过指定的key隔离上下文,完成不同的bean可以获取到不同的配置。
(3)开启熔断后,FeignClientFactoryBean的builder就是HystrixFeign.Builder,实现了Feign.Builder,重写了其build方法,并且也有相应的调用处理器HystrixInvocationHandler和HystrixDelegatingContract(基于现有的Contract修改了返回类型)。
(4)feignClient的初始化对象是基于jdk的动态代理。