/**
* 经纪人,动态代理
*
* @author 石玉森
**/
public class JDKDynamicProxyFactory<T> implements InvocationHandler {
/**
* 委托类实例:被代理的真实对象实例
*/
private T target;
public JDKDynamicProxyFactory(T target) {
this.target = target;
}
/**
*
* @param proxy 生成的代理类实例
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用被被代理的方法 before");
Object result = method.invoke(target,args);
System.out.println("调用被被代理的方法 after");
return result;
}
/**
* 创建代理类实例
* @return
*/
public T getProxyInstance(){
ClassLoader classLoader = target.getClass().getClassLoader();
Class[] interfaces = target.getClass().getInterfaces();
Object proxy = Proxy.newProxyInstance(classLoader,interfaces,this);
return (T) proxy;
}
}
JDK动态代理是基于java反射来实现。
**
* cglib动态代理实现
*
* @author 石玉森
**/
public class CglibDynamicProxyFactory<T> implements MethodInterceptor {
/**
* 被代理类:委托类
*/
private T target;
/**
* @param o 代理的对象(生成的被代理类的子类实例)
* @param method 被代理的方法
* @param objects 被代理的方法的参数
* @param methodProxy 代理的对的方法(生成的被代理类的子类实例)
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
System.out.println("调用被被代理的方法 before");
// result = method.invoke(o,objects);//不对
result = method.invoke(this.target, objects);//可以
// result = methodProxy.invoke(this.target, objects);//可以
// result = methodProxy.invokeSuper(o, objects);//可以
System.out.println("调用被被代理的方法 after");
return result;
}
public T getProxyInstance(T target) {
this.target=target;
Enhancer enhancer = new Enhancer();
//设置创建子类的类,即指定为哪个类产生代理类
enhancer.setSuperclass(target.getClass());
/*设置回调函数 setCallback设置被代理类的public非final方法被调用时的处理类
* */
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return (T) enhancer.create();
}
}
实现原理
代理模式 | 优点 | 缺点 |
---|---|---|
静态代理 | 简单 | 代码不能复用 |
JDK动态代理 | 动态代码生成快 | 执行慢,强制实现接口 |
CGLIB动态代理 | 生成代码慢 | 执行快,不需实现接口 |
/***
* 静态代理:实现List
* 随机存取:实现RandomAccess
* 克隆:实现Cloneable
*/
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
final transient ReentrantLock lock = new ReentrantLock();
//委托类。初始化时即实例化,不像虚拟代理懒加载
private transient volatile Object[] array;
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
}
struts2中的拦截器实现
/**
* 服务生产者
* 服务生产者接受到消费方的调用,通过反射调起实际接口
*/
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
try {
String interfaceName = input.readUTF();
String methodName = input.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
Object[] arguments = (Object[]) input.readObject();
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
try {
if (!interfaceName.equals(interfaceClazz.getName())) {
throw new IllegalAccessException("Interface wrong, export:" + interfaceClazz + " refer:" + interfaceName);
}
Method method = service.getClass().getMethod(methodName, parameterTypes);
Object result = method.invoke(service, arguments);
output.writeObject(result);
} catch (Throwable t) {
output.writeObject(t);
} finally {
output.close();
}
} finally {
input.close();
}
/**
* 服务消费方
* 服务消费方在本地通过代理的模式实例化代理类,代理类内部通过socket调用远程生产者
*/
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket socket =null;
try {
socket = new Socket(host, port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
try {
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
try {
Object result = input.readObject();
return result;
} finally {
input.close();
}
} finally {
output.close();
}
} finally {
socket.close();
}
}
});