在框架开发中动态代理模式使用较为普遍,与此同时JDK为我们提供了好用的接口,
1.InvocationHandler(代理接口,代理类需要实现它)
2.Proxy(代理类,用来实现代理操作)
实例
项目结构
Proxy(自定义的代理接口类,并非jdk自带的)
public interface Proxy {
void show(User user);
}
POJO 类 User
@AllArgsConstructor
@ToString
public class User {
private String name;
private Integer age;
}
ProxyUser(代理类)
@AllArgsConstructor
public class ProxyUser implements InvocationHandler {
private Proxy proxy;
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("ProxyUser :: invoke() ----------进入-----------");
method.invoke(proxy,args);
System.out.println("ProxyUser :: invoke() ----------退出-----------");
return null;
}
}
TargetUser (实际目标类)
public class TargetUser implements Proxy {
public void show(User user){
System.out.println("TargetUser :: show(): "+user.toString());
}
}
测试类 Test
public class Test {
public static void main(String[] args) {
TargetUser targetUser=new TargetUser();
InvocationHandler invocationHandler=new ProxyUser(targetUser);
com.ecit.lyy.proxy.dynamic_proxy.Proxy proxy=(com.ecit.lyy.proxy.dynamic_proxy.Proxy)Proxy.newProxyInstance(
invocationHandler.getClass().getClassLoader(),
targetUser.getClass().getInterfaces(),
invocationHandler);
proxy.show(new User("show.tom",15));
}
}
结果如下
ProxyUser :: invoke() ----------进入-----------
TargetUser :: show(): User(name=show.tom, age=15)
ProxyUser :: invoke() ----------退出-----------
注意点
1.代理类实现的是jdk中的InvocationHandler接口,而非我们自定义的接口。
2.目标类实现的是自定义的Proxy接口,而非JDK自带的Proxy。
3.代理类通过实现InvocationHandler的invoke方法,来处理实际业务逻辑,我们可以在method.invoke()前后加入我们自己的逻辑。
4.使用Proxy.newProxyInstance来实现代理,它有三个参数
源码(它们的使用方式在源码里都有)
InvocationHandler (接口)
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
Proxy(jdk)
package java.lang.reflect;
import (省略。。)
/**
* InvocationHandler handler = new MyInvocationHandler(...);
* Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
* Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
* newInstance(handler);
* 或者:
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
* new Class[] { Foo.class },
* handler);
*/
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
......
protected InvocationHandler h;
private Proxy() {
}
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
......
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);//为非空对象
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
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())) {
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);
}
}
......
public static boolean isProxyClass(Class<?> cl) {
return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
@CallerSensitive
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
{
/*
* Verify that the object is actually a proxy instance.
*/
if (!isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("not a proxy instance");
}
final Proxy p = (Proxy) proxy;
final InvocationHandler ih = p.h;
if (System.getSecurityManager() != null) {
Class<?> ihClass = ih.getClass();
Class<?> caller = Reflection.getCallerClass();
if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
ihClass.getClassLoader()))
{
ReflectUtil.checkPackageAccess(ihClass);
}
}
return ih;
}
private static native Class<?> defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);
}