Java动态代理
Posted Se7end
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java动态代理相关的知识,希望对你有一定的参考价值。
最近看了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 <T> */ public interface Target<T> { public Class<T> type(); public static class HardCodedTarget<T> implements Target<T> { private Class<T> type; public HardCodedTarget(Class<T> type) { this.type = type; } @Override public Class<T> type() { return type; } } }
5.代理工具类
/** * 代理工具类 */ public class ProxyUtil { public static <T> T newInstance(Target<T> target) { Map<String, MethodHandler> nameToHandler = MethodHandler.FactoryMethodHandler.apply(target); Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>(); 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<Method, MethodHandler> dispatch; public DefaultInvocationHandler(Target<?> target, Map<Method, MethodHandler> 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<String, MethodHandler> apply(Target<?> target) { System.out.println("初始化代理>>>"); Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>(); 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注解来处理代理方法的业务逻辑。
以上是关于Java动态代理的主要内容,如果未能解决你的问题,请参考以下文章