代理是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。
定义一个接口如下:
package com.org.base.proxy;
public interface BookOderService {
public void sell(int num);
}
定义一个实现类如下:
package com.org.base.proxy;
public class BookOderServiceImpl implements BookOderService {
@Override
public void sell(int num) {
System.out.println("num = [" + num + "]");
}
}
定义一个代理工具处理类ProxyHandler 实现InvocationHandler
package com.org.base.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
private Object object;
public ProxyHandler(Object object) {
this.object=object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* ①Object proxy:代理对象引用。
* ②Method method:代理类中接受的接口方法。
* ③Object[] args:向代理对象的方法中传递的参数。
*/
System.out.println("<执行方法之前>");
Object result = method.invoke(object, args);
System.out.println("<执行方法之后>");
return result;
}
}
测试主函数调用
package com.org.base.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) throws Exception {
BookOderServiceImpl bookOderServiceImpl=new BookOderServiceImpl();
BookOderService bookOderService=(BookOderService)Proxy.newProxyInstance(BookOderService.class.getClassLoader(),new Class[]{BookOderService.class},new ProxyHandler(bookOderServiceImpl));
bookOderService.sell(1);
}
}
Proxy源码分析:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//判断当前传入的代理类是否为空
Objects.requireNonNull(h);
// 对 interfaces 数组的浅拷贝
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// 如果配置了安全管理器,那么需要确认 Proxy 有创建新的代理类的许可
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
// 调用 getProxyClass0
Class<?> cl = getProxyClass0(loader, intfs);
......
}
调用getProxyClass0 方法:
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
// 确认需要进行增强的接口数量少于等于 65535,详细原因请去了解 ClassFile 规范(规范中的接口上限)
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 如果需要由指定 ClassLoader 加载, 实现给定 interfaces 的代理类已经存在,
// 将直接返回已经缓存过的拷贝
// 否则,通过 ProxyClassFactory 创建新的代理类
return proxyClassCache.get(loader, interfaces);
}