代理模式的作用是为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
由于静态代理会导致类文件大量增多,所以 Java 中动态代理使用的较多。
JDK 中的动态代理的使用,实现 InvocationHandler 接口,只能代理接口的实现类
package com.xiongjun.proxy.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK 自带动态代理
*
* @author ConstXiong
*/
public class JdkDynamicProxy implements InvocationHandler {
private Object target;
public JdkDynamicProxy(Object target) {
this.target = target;
}
@SuppressWarnings("unchecked")
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
long t1 = System.currentTimeMillis();
result = method.invoke(target, args);//目标类的方法调用,与结果获取
System.out.println("login cost time : " + (System.currentTimeMillis() - t1));
return result;
}
}
客户端代码:
JdkDynamicProxy proxy = new JdkDynamicProxy(new ServiceImpl());
Service jdkService = proxy.getProxy();
jdkService.login("", "");
InvocationHandler 接口的源码,是被代理实例的处理程序实现,代理实例的方法调用会被关联到 invoke 方法
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
代理实例通过 Proxy 类的静态工厂方法 newProxyInstance 创建
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();//复制接口的Class对象数组
//校验权限
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//调用本地方法根据类加载器和Class对象数组,获取被代理对象的Class的对象
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取构造方法对象
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {//非public修改可见权限
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});//创建被代理对象实例
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
ConstXiong 备案号:苏ICP备16009629号-3