我们知道在springcloud中在引入FeignClient注解的接口可以通过动态代理获取配置了name属性和fallback属性的值然后进行服务器之间的跨服务访问,若调用失败会降级处理,根据我近期的了解做了一个很简单的demo,其中动态代理也用的JDK自带,接下来请看代码分析,不一定和框架一样。仅做参考
1.创建动态代理类
package com.gg;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Class<?> target;
public JDKProxy(Class<?> target) {
this.target = target;
}
public Object createInstance() {
return Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启跨服务调用");
Object object = null;
Driver annotation = null;
try {
Class<?> declaringClass = method.getDeclaringClass();
annotation = declaringClass.getAnnotation(Driver.class);
Request annotation1 = method.getAnnotation(Request.class);
String value = annotation1.value();//获取路径
String name = annotation.name();//根据配置的name获取注册中心的微服务
System.out.println(name);
System.out.println(value);
//即可访问name微服务下路径为value的方法
int i = 1/0;//模拟服务间调用时抛出的异常
System.out.println("服务之间访问成功");
} catch (RuntimeException e) {
Class<?> fallback = annotation.fallback();
Object o = fallback.newInstance();
method.invoke(o, args);
}
return object;
}
}
2.跨服务业务调用接口
package com.gg;
import java.util.List;
@Driver(name="prj",fallback = Bus.class)
public interface Tool {
@Request("/getAllListFromPrj")
List<String> getAllListFromPrj();
}
3.实现类
package com.gg;
import java.util.List;
public class Bus implements Tool {
@Override
public List<String> getAllListFromPrj() {
System.out.println("获取失败,服务器降级处理");
return null;
}
}
4.@Driver类比于@FeignClient,其中name是注册表中的微服务名,fallback降级类
package com.gg;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Driver {
Class<?> fallback();
String name() default "";
}
5.@Request模拟@Request,value为路径
package com.gg;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Request {
String value();
}
6.测试
package com.gg;
public class Test {
public static void main(String[] args) {
JDKProxy jdkProxy = new JDKProxy(Tool.class);
Tool instance = (Tool) jdkProxy.createInstance();
instance.getAllListFromPrj();
}
}
7.测试结果
开启跨服务调用
prj
/getAllListFromPrj
获取失败,服务器降级处理
7.总结,在实际应用中,只要注入了@Autowired注解的接口,就可以根据此接口类型进行动态代理,并根据相应配置访问指定服务,当然这只是一个很简易的demo很多其他情况是没有考虑的,仅仅作为思路上的一种考量。