博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java动态代理
阅读量:4951 次
发布时间:2019-06-11

本文共 8082 字,大约阅读时间需要 26 分钟。

最近看了Feign的远程调用代理这部分的代码,尝试的自己写了一下。

 

调用模型图:

 

 

1.ProxyMethod注解,判断方法是否需要做代理。

/** * 代理方法注解 */@java.lang.annotation.Target(METHOD)@Retention(RUNTIME)public @interface ProxyMethod {    public String value();}

2.启动类,idService是生成的代理类。

public class StartApplication {    public static void main(String[] args) {        // 创建代理        IdService idService = ProxyUtil.newInstance(new Target.HardCodedTarget<>(IdService.class));        // 执行代理方法        Integer id = idService.getId();        System.out.println(id);    }}

3.IdService服务类

public interface IdService {    @ProxyMethod("getId")    public Integer getId();}

4.类代理

/** * 代理 * @param 
*/public interface Target
{ public Class
type(); public static class HardCodedTarget
implements Target
{ private Class
type; public HardCodedTarget(Class
type) { this.type = type; } @Override public Class
type() { return type; } }}

5.代理工具类

/** * 代理工具类 */public class ProxyUtil {    public static 
T newInstance(Target
target) { Map
nameToHandler = MethodHandler.FactoryMethodHandler.apply(target); Map
methodToHandler = new LinkedHashMap
(); for (Method method : target.type().getMethods()) { if (method.getDeclaringClass() == Object.class) { continue; } else if (isDefault(method)) { MethodHandler.DefaultMethodHandler handler = new MethodHandler.DefaultMethodHandler(method); methodToHandler.put(method, handler); } else { System.out.println("ProxyUtil.newInstance.Method:" + method.getName()); methodToHandler.put(method, nameToHandler.get(configKey(target.type(), method))); } } InvocationHandler handler = new DefaultInvocationHandler(target, methodToHandler); @SuppressWarnings("unchecked") T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class
[]{target.type()}, handler); return proxy; } public static String configKey(Class
targetType, Method method) { StringBuilder builder = new StringBuilder(); builder.append(targetType.getSimpleName()); builder.append('#').append(method.getName()).append('('); for (Type param : method.getGenericParameterTypes()) { builder.append(getRawType(param)).append(','); } if (method.getParameterTypes().length > 0) { builder.deleteCharAt(builder.length() - 1); } return builder.append(')').toString(); } public static String getRawType(Type param) { return param.getTypeName(); } /** * Identifies a method as a default instance method. */ public static boolean isDefault(Method method) { // Default methods are public non-abstract, non-synthetic, and non-static instance methods // declared in an interface. // method.isDefault() is not sufficient for our usage as it does not check // for synthetic methods. As a result, it picks up overridden methods as well as actual default methods. final int SYNTHETIC = 0x00001000; return ((method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)) == Modifier.PUBLIC) && method.getDeclaringClass().isInterface(); } /** * 自定义方法代理 */ public static class DefaultInvocationHandler implements InvocationHandler { private final Target
target; private final Map
dispatch; public DefaultInvocationHandler(Target
target, Map
dispatch) { this.target = target; this.dispatch = dispatch; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("equals".equals(method.getName())) { try { Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null; return equals(otherHandler); } catch (IllegalArgumentException e) { return false; } } else if ("hashCode".equals(method.getName())) { return hashCode(); } else if ("toString".equals(method.getName())) { return toString(); } return dispatch.get(method).invoke(args); } @Override public boolean equals(Object obj) { if (obj instanceof DefaultInvocationHandler) { DefaultInvocationHandler other = (DefaultInvocationHandler) obj; return target.equals(other.target); } return false; } @Override public int hashCode() { return target.hashCode(); } @Override public String toString() { return target.toString(); } }}

6.代理方法处理类

public interface MethodHandler {    Object invoke(Object[] argv) throws Throwable;    public static class DefaultMethodHandler implements MethodHandler {        private final MethodHandle unboundHandle;        private MethodHandle handle;        public DefaultMethodHandler(Method defaultMethod) {            try {                Class
declaringClass = defaultMethod.getDeclaringClass(); Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); field.setAccessible(true); MethodHandles.Lookup lookup = (MethodHandles.Lookup) field.get(null); this.unboundHandle = lookup.unreflectSpecial(defaultMethod, declaringClass); } catch (NoSuchFieldException ex) { throw new IllegalStateException(ex); } catch (IllegalAccessException ex) { throw new IllegalStateException(ex); } } /** * Bind this handler to a proxy object. After bound, DefaultMethodHandler#invoke will act as if it was called * on the proxy object. Must be called once and only once for a given instance of DefaultMethodHandler */ public void bindTo(Object proxy) { if (handle != null) { throw new IllegalStateException("Attempted to rebind a default method handler that was already bound"); } handle = unboundHandle.bindTo(proxy); } /** * Invoke this method. DefaultMethodHandler#bindTo must be called before the first * time invoke is called. */ @Override public Object invoke(Object[] argv) throws Throwable { if (handle == null) { throw new IllegalStateException("Default method handler invoked before proxy has been bound."); } return handle.invokeWithArguments(argv); } } public static class FactoryMethodHandler { public static Map
apply(Target
target) { System.out.println("初始化代理>>>"); Map
result = new LinkedHashMap
(); Class
targetType = target.type(); for (Method method : targetType.getMethods()) { if (method.getDeclaringClass() == Object.class || (method.getModifiers() & Modifier.STATIC) != 0 || ProxyUtil.isDefault(method)) { continue; } result.put(ProxyUtil.configKey(targetType, method), new ProxyMethodHandler(method)); } return result; } } public static class ProxyMethodHandler implements MethodHandler { private Method method; public ProxyMethodHandler(Method method) { this.method = method; } @Override public Object invoke(Object[] argv) throws Throwable { System.out.println("执行代理方法>>>"); ProxyMethod proxyMethod = method.getAnnotation(ProxyMethod.class); if (null != proxyMethod) { if ("getId".equals(proxyMethod.value())) { return 1; } } return null; } }}

 

在ProxyMethodHandler方法的invoke方法中,根据ProxyMethod注解来处理代理方法的业务逻辑。

 

作者:

声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接。

 

转载于:https://www.cnblogs.com/se7end/p/10419793.html

你可能感兴趣的文章
异常实验
查看>>
python \r与\b的应用、光标的含义
查看>>
深拷贝 vs 浅拷贝 释放多次
查看>>
Java环境变量PATH和CLASSPATH
查看>>
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME) 就是补存在这个列名
查看>>
assert 的作用是什么?
查看>>
收藏夹(持续更新)
查看>>
iOS中的#import和class区别
查看>>
节约内存,请使用标签页管理工具:onetab、better onetab
查看>>
jQuery中的事件与动画
查看>>
页面加载骨架
查看>>
关于android系统不关屏设置
查看>>
SONY VPCS138EC降级安装XP
查看>>
[luogu4201][bzoj1063]设计路线【树形DP】
查看>>
手机抓包-手机劫持域名到指定服务器
查看>>
被放逐的皇后 金建云
查看>>
Javascript 有用参考函数
查看>>
点群的判别(三)
查看>>
GNSS 使用DFT算法 能量损耗仿真
查看>>
网页抓取 总结
查看>>