我们首先先把主流程跑一遍,回头再分析分析细节,题外说一句,自己分析下源码细节可以加深印象
首先要说下,要开启Feign,需要在主启动类上加上@EnableFeignClients
看下这个注解,会发现在Spring容器中注入了一个FeignClientsRegistrar.class
接下来,好好看看这个注册类,主要的步骤我都加上注释了:
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
// patterned after Spring Integration IntegrationComponentScanRegistrar
// and RibbonClientsConfigurationRegistgrar
private ResourceLoader resourceLoader;
private ClassLoader classLoader;
private Environment environment;
public FeignClientsRegistrar() {
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
//这个是该类的入口方法,在该方法中向Spring容器注入要导入的类
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//配置类包装,注入Spring容器
registerDefaultConfiguration(metadata, registry);
//注册FeignClientFactoryBean 核心类
registerFeignClients(metadata, registry);
}
private void registerDefaultConfiguration(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//获取@EnableFeignClients注解的配置属性
Map<String, Object> defaultAttrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
//如果当前配置中包含defaultConfiguration属性
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
String name;
//判断当期类是不是嵌套类或者内部类来拼接Name
//一般都不是嵌套类 例如:name = "default."+主启动类全限定名称
if (metadata.hasEnclosingClass()) {
name = "default." + metadata.getEnclosingClassName();
}
else {
name = "default." + metadata.getClassName();
}
//将该配置类注入其中
//其实注入的是FeignClientSpecification配置类,该类的配置项为defaultConfiguration配置的属性类,name为"default."+主启动类全限定名称
//这个后面Feign容器初始化时候要用到
registerClientConfiguration(registry, name,
defaultAttrs.get("defaultConfiguration"));
}
}
public void registerFeignClients(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//获取扫描器
ClassPathScanningCandidateComponentProvider scanner = getScanner();
//注入类加载器
scanner.setResourceLoader(this.resourceLoader);
Set<String> basePackages;
//获取注解的属性值
Map<String, Object> attrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName());
//增加注解过滤器
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
FeignClient.class);
//获取配置的扫描类
final Class<?>[] clients = attrs == null ? null
: (Class<?>[]) attrs.get("clients");
//一般都没有配置扫描类
if (clients == null || clients.length == 0) {
//加入注解过滤器 过滤出含有FeignClient注解的类
scanner.addIncludeFilter(annotationTypeFilter);
//解析扫描路径
basePackages = getBasePackages(metadata);
}
else {
final Set<String> clientClasses = new HashSet<>();
basePackages = new HashSet<>();
for (Class<?> clazz : clients) {
basePackages.add(ClassUtils.getPackageName(clazz));
clientClasses.add(clazz.getCanonicalName());
}
AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
@Override
protected boolean match(ClassMetadata metadata) {
String cleaned = metadata.getClassName().replaceAll("\\$", ".");
return clientClasses.contains(cleaned);
}
};
scanner.addIncludeFilter(
new AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
}
//遍历扫描路径
for (String basePackage : basePackages) {
//扫描路径下的含有@FeignClient注解的类 scanner中也进行过滤
Set<BeanDefinition> candidateComponents = scanner
.findCandidateComponents(basePackage);
//遍历扫描出的类
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
//如果不是接口中断运行
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClient can only be specified on an interface");
//获取@FeginClient配置的属性
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(
FeignClient.class.getCanonicalName());
//从配置属性中找到服务名称 优先级由低到高 value->name->serviceId
String name = getClientName(attributes);
//这个地方又是将@FeginClient中的配置类封装注入到Spring容器中
//name 就是服务名称
registerClientConfiguration(registry, name,
attributes.get("configuration"));
//核心代码 注入FeignClientFactoryBean
registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
//这个方法是注入FeginClint的核心工厂
private void registerFeignClient(BeanDefinitionRegistry registry,
AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
//获取被@FeginClient标注的类名
String className = annotationMetadata.getClassName();
//获取FeignClientFactoryBean的BeanDefinition构造器
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
validate(attributes);
//把注解中的属性注入到BeanDefinition构造类中
//自动拼接 "http://"
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("path", getPath(attributes));
String name = getName(attributes);
definition.addPropertyValue("name", name);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
//设置类型注入
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
//设置别名 例如ServiceA + FeignClient
String alias = name + "FeignClient";
//获取FeignClientFactoryBean的BeanDefinition
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
//一般为true
boolean primary = (Boolean)attributes.get("primary"); // has a default, won't be null
beanDefinition.setPrimary(primary);
//如果设置了别名,以设置为主
String qualifier = getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
//注册FeignClientFactoryBean的BeanDefinition
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
new String[] { alias });
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
private void validate(Map<String, Object> attributes) {
AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes);
// This blows up if an aliased property is overspecified
annotation.getAliasedString("name", FeignClient.class, null);
}
/* for testing */ String getName(Map<String, Object> attributes) {
String name = (String) attributes.get("serviceId");
if (!StringUtils.hasText(name)) {
name = (String) attributes.get("name");
}
if (!StringUtils.hasText(name)) {
name = (String) attributes.get("value");
}
name = resolve(name);
if (!StringUtils.hasText(name)) {
return "";
}
String host = null;
try {
String url;
if (!name.startsWith("http://") && !name.startsWith("https://")) {
url = "http://" + name;
} else {
url = name;
}
host = new URI(url).getHost();
}
catch (URISyntaxException e) {
}
Assert.state(host != null, "Service id not legal hostname (" + name + ")");
return name;
}
private String resolve(String value) {
if (StringUtils.hasText(value)) {
return this.environment.resolvePlaceholders(value);
}
return value;
}
private String getUrl(Map<String, Object> attributes) {
String url = resolve((String) attributes.get("url"));
if (StringUtils.hasText(url) && !(url.startsWith("#{") && url.contains("}"))) {
if (!url.contains("://")) {
url = "http://" + url;
}
try {
new URL(url);
}
catch (MalformedURLException e) {
throw new IllegalArgumentException(url + " is malformed", e);
}
}
return url;
}
private String getPath(Map<String, Object> attributes) {
String path = resolve((String) attributes.get("path"));
if (StringUtils.hasText(path)) {
path = path.trim();
if (!path.startsWith("/")) {
path = "/" + path;
}
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
}
return path;
}
protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(
AnnotatedBeanDefinition beanDefinition) {
//如果当前类是非嵌套类
if (beanDefinition.getMetadata().isIndependent()) {
// TODO until SPR-11711 will be resolved
//下面这个一般不满足
if (beanDefinition.getMetadata().isInterface()
&& beanDefinition.getMetadata()
.getInterfaceNames().length == 1
&& Annotation.class.getName().equals(beanDefinition
.getMetadata().getInterfaceNames()[0])) {
try {
Class<?> target = ClassUtils.forName(
beanDefinition.getMetadata().getClassName(),
FeignClientsRegistrar.this.classLoader);
return !target.isAnnotation();
}
catch (Exception ex) {
this.logger.error(
"Could not load target class: "
+ beanDefinition.getMetadata().getClassName(),
ex);
}
}
return true;
}
return false;
}
};
}
//扫描路径设置 一般默认
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
//获取EnableFeignClients中的配置属性
Map<String, Object> attributes = importingClassMetadata
.getAnnotationAttributes(EnableFeignClients.class.getCanonicalName());
Set<String> basePackages = new HashSet<>();
// 如果配置了value 数组,依次加入扫描路径
for (String pkg : (String[]) attributes.get("value")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
// 如果配置了basePackages 数组,依次加入扫描路径
for (String pkg : (String[]) attributes.get("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
// 如果配置了basePackageClasses 扫描类数组,找到类全限定名称,依次加入扫描路径
for (Class<?> clazz : (Class[]) attributes.get("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
//如果都没配置,以主启动类的全限定路径为根目录进行扫描
if (basePackages.isEmpty()) {
basePackages.add(
ClassUtils.getPackageName(importingClassMetadata.getClassName()));
}
return basePackages;
}
private String getQualifier(Map<String, Object> client) {
if (client == null) {
return null;
}
String qualifier = (String) client.get("qualifier");
if (StringUtils.hasText(qualifier)) {
return qualifier;
}
return null;
}
private String getClientName(Map<String, Object> client) {
if (client == null) {
return null;
}
String value = (String) client.get("value");
if (!StringUtils.hasText(value)) {
value = (String) client.get("name");
}
if (!StringUtils.hasText(value)) {
value = (String) client.get("serviceId");
}
if (StringUtils.hasText(value)) {
return value;
}
throw new IllegalStateException("Either 'name' or 'value' must be provided in @"
+ FeignClient.class.getSimpleName());
}
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());
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Helper class to create a {@link TypeFilter} that matches if all the delegates
* match.
*
* @author Oliver Gierke
*/
private static class AllTypeFilter implements TypeFilter {
private final List<TypeFilter> delegates;
/**
* Creates a new {@link AllTypeFilter} to match if all the given delegates match.
*
* @param delegates must not be {@literal null}.
*/
public AllTypeFilter(List<TypeFilter> delegates) {
Assert.notNull(delegates);
this.delegates = delegates;
}
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
for (TypeFilter filter : this.delegates) {
if (!filter.match(metadataReader, metadataReaderFactory)) {
return false;
}
}
return true;
}
}
}
其实没什么重要的核心方法,主要完成这几步骤:
- 获取@FeignClient,@EnableFeignClients注解中的 configuration,defaultConfiguration的配置属性,封装成FeignClientSpecification配置类,注入Spring容器中
- 扫描出取@FeignClient的接口,取出接口中封装的属性值,例如 url,serverId,fallback,decode404等属性,构造FeignClientFactoryBean,填充获取到的属性,将该Bean注入到Spring容器中,这里注意了啊,扫描的每个接口都会构造一个FeignClientFactoryBean,bean对应的name为接口名称,所以可以猜想下,同一个ServerId可以有多个接口,不会覆盖的!
下面我们看看注入到Spring容器的FeginClientFactoryBean是怎么初始化的?
首先看看继承实现体系:
class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean,
ApplicationContextAware
它实现了FactoryBean接口,那么就很有意思了,Spring在对这个类型的BeanDefinition构造实例会调用getObject()方法,我们看看getObject()方法吧,一行一行看
FeignContext context = applicationContext.getBean(FeignContext.class);
获取Fegin的容器,这个和Ribbon获取Server上下文类似
org.springframework.cloud.netflix.feign.FeignAutoConfiguration
public class FeignAutoConfiguration {
@Autowired(required = false)
private List<FeignClientSpecification> configurations = new ArrayList<>();
@Bean
public HasFeatures feignFeature() {
return HasFeatures.namedFeature("Feign", Feign.class);
}
@Bean
public FeignContext feignContext() {
FeignContext context = new FeignContext();
context.setConfigurations(this.configurations);
return context;
}
//省略………………
}
首先configurations集合注入,是我们上文中说的注解中配置的配置类封装实例,将该配置集合加入context中,跟进源码会发现,当前的服务对应的上下文还未构建,在获取的时候构建的,看set方法
public void setConfigurations(List<C> configurations) {
for (C client : configurations) {
this.configurations.put(client.getName(), client);
}
}
要是一个服务对应多个接口,会出现覆盖情况啊!
这块强调下,FeginContext是实现了NamedContextFactory,所有服务共享一个NamedContextFactory,在该实例的属性中有Map<String, AnnotationConfigApplicationContext> contexts ,这里填充的是服务名称对应的上下文,那么在什么时候触发上下文的构建呢,类似Ribbon,在进行获取服务的上下文的时候进行构建,我们看看构建代码:
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);
}
context.refresh();
return context;
}
和Ribbon一样,默认情况下,如果没有配置configuration等相关的配置类,那么默认的就是一个configuration生效了,是构造传入的
super(FeignClientsConfiguration.class, "feign", "feign.client.name");
看看这个FeignClientsConfiguration配置类里面配置了哪些属性:
- Decoder -> ResponseEntityDecoder 解码器
- Encoder -> SpringEncoder 编码器
- Contract -> SpringMvcContract 注解解释器
- Retryer -> Retryer.NEVER_RETRY
- FeignLoggerFactory -> DefaultFeignLoggerFactory
- FormattingConversionService
主要配置了这些属性,这些属性后续们会用到,在FeginConext构造的时候还得看一点,它设置了父级容器
context.setParent(this.parent);
NamedContextFactory是实现了ApplicationContextAware接口的,在setApplicationContext(ApplicationContext parent)方法中将SpringApplicationContext赋值给parent,所以FeginContext是SpringApplicationContext的子容器,这个有什么用呢,在获取Bean的时候会用到,如果子容器没有会去父级容器中寻找,那么咋们考虑一个问题,在Spring上下文中,FeignClientsConfiguration实例化得各个Bean在各个子上下文中都有一个单独实例,共用服务还是从父级容器中获取单例Bean。
回到主方法:
Feign.Builder builder = feign(context);
//子方法
protected Feign.Builder feign(FeignContext context) {
FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
Logger logger = loggerFactory.create(this.type);
// @formatter:off
Feign.Builder builder = get(context, Feign.Builder.class)
// required values
.logger(logger)
.encoder(get(context, Encoder.class))
.decoder(get(context, Decoder.class))
.contract(get(context, Contract.class));
// @formatter:on
configureFeign(context, builder);
return builder;
}
- 第一步获取到一个FeignLoggerFactory,在子容器中咋们实例化的是DefaultFeignLoggerFactory,所以这里获取到的就是这个
- 创建一个Logger对象
- 创建一个Feign.Builder,子容器中实例化的,设置相关的解析器
- 设置属性,有优先级
设置属性这块代码,咋们看看,是通过注入顺序来控制优先级的
protected void configureFeign(FeignContext context, Feign.Builder builder) {
FeignClientProperties properties = applicationContext.getBean(FeignClientProperties.class);
if (properties != null) {
//默认为true
if (properties.isDefaultToProperties()) {
//先注入注解属性中configuration配置的配置类
configureUsingConfiguration(context, builder);
//注入全局配置属性
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
//注入针对单个服务的配置属性
configureUsingProperties(properties.getConfig().get(this.name), builder);
} else {
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
configureUsingProperties(properties.getConfig().get(this.name), builder);
configureUsingConfiguration(context, builder);
}
} else {
configureUsingConfiguration(context, builder);
}
}
从上面知道了我们配置的属性优先级由低到高是
注解的configuration配置类 -> 配置的全局属性 -> 针对单个服务配置的属性
全局属性就是这样:
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
针对单个服务配置的属性:
feign:
client:
config:
ServiceA:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
decode404: false
回归主函数方法getObject(),我们接着分析
if (!StringUtils.hasText(this.url)) {
String url;
if (!this.name.startsWith("http")) {
url = "http://" + this.name;
}
else {
url = this.name;
}
url += cleanPath();
return loadBalance(builder, context, new HardCodedTarget<>(this.type,
this.name, url));
}
这个URL用来指定要发送的服务地址,但是都用Ribbon做负载均衡了,一般不配置,所以会进入该逻辑代码中:
- 首先判断下name是否是http开头的,如果没有就加上
- 拼接映射路径前缀,一般不配置
- 进入loadBalance()方法
最后的核心方法就是loadbalance()方法,先看看:
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
HardCodedTarget<T> target) {
Client client = getOptional(context, Client.class);
if (client != null) {
builder.client(client);
Targeter targeter = get(context, Targeter.class);
return targeter.target(this, builder, context, target);
}
throw new IllegalStateException(
"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}
首先返回一个Client,它的实现类为LoadBalancerFeignClient,这个注入不在子容器中,getBean()是先优先在自己容器中寻找,如果没有再从父级容器中寻找,我们想想,如果按照这个逻辑,多个服务获取到的Clinet是父级的单例实例!
接着下一步,获取到了Client,将该LoadBalancerFeignClient注入到Builer中,之后获取Targeter,实现类是HystrixTargeter,接着又是一个方法,看看吧。
@Override
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
Target.HardCodedTarget<T> target) {
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
return feign.target(target);
}
feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
SetterFactory setterFactory = getOptional(factory.getName(), context,
SetterFactory.class);
if (setterFactory != null) {
builder.setterFactory(setterFactory);
}
Class<?> fallback = factory.getFallback();
if (fallback != void.class) {
return targetWithFallback(factory.getName(), context, target, builder, fallback);
}
Class<?> fallbackFactory = factory.getFallbackFactory();
if (fallbackFactory != void.class) {
return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory);
}
return feign.target(target);
}
首先看起来很麻烦,慢慢来吧,
首先判断feign instanceof feign.hystrix.HystrixFeign.Builder,当时说过Fegin.Builder是在子容器实例化的,我们看看实例化的类是怎么回事:
class Builder extends Feign.Builder
所以这块判断是false,直接进入 feign.target(target)方法:
public <T> T target(Target<T> target) {
return build().newInstance(target);
}
两个方法,build()和newInstance(target)方法,先看build()
public Feign build() {
SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
logLevel, decode404);
ParseHandlersByName handlersByName =
new ParseHandlersByName(contract, options, encoder, decoder,
errorDecoder, synchronousMethodHandlerFactory);
return new ReflectiveFeign(handlersByName, invocationHandlerFactory);
}
- 使用一堆组件构造构造SynchronousMethodHandler,这个后面会知道干什么用的,核心类,动态代理主要靠这个玩的
- 构建ParseHandlersByName
- 使用SynchronousMethodHandler和ParseHandlersByName构建一个ReflectiveFeign
接着看看newInstance方法,这个方法是整个构建的核心,主要的动态代理是这个方法实现的
public <T> T newInstance(Target<T> target) {
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
for (Method method : target.type().getMethods()) {
if (method.getDeclaringClass() == Object.class) {
continue;
} else if(Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
InvocationHandler handler = factory.create(target, methodToHandler);
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);
for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
第一步是解析接口方法,使用SpringMVCContract解析方法参数生成SynchronousMethodHandler:
[图片上传失败...(image-f785b6-1628498535860)]
[图片上传失败...(image-42d0bb-1628498535860)]
这里面包含了方法的解析参数,其中SynchronousMethodHandler.metedata为方法的元数据,具体的是使用SpringMVCContract解析注册参数获得元数据。
下面这一步,就是很简单的将Map<name,SynchronousMethodHandler>替换为Map<Method,SynchronousMethodHandler>
主要也是为了方便使用原有方法映射封装方法。
InvocationHandler handler = factory.create(target, methodToHandler);
这一步就是创建InvocationHandler
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);
创建动态代理对象,使用的是JDK的动态代理
从这些步骤可以看出,真正执行请求方法的是封装在SynchronousMethodHandler中逻辑,后面再说
主要的构造逻辑就这些了