参考:《java程序性能优化》--葛一鸣
代理模式,屏蔽用户对真实对象的访问,而用代理对象完成用户请求。
好处:
(1)安全,屏蔽客户端之间访问真实对象。
(2)增加真实对象功能,比如spring的拦截器,利用代理模式,实现方法前和方法后等拦截。、
(3)延迟加载
角色:
主题接口、真实主题、代理类、客户端主类
1、普通代理模式
public interface IQuery{
public String request();
}
public class Query implements IQuery{
public Query(){
...
}
public String request(){
return "request";
}
}
public class QueryProxy implements IQuery{
private Query query=null;
public String request(){
if(query!=null)
real=new Query():
return real;
}
}
public Class Client{
public static void main(String[] args){
IQuery query=new QueryProxy();
query.request();
}
}
2、动态代理
动态代理是指在运行时,动态生成代理类。即,代理类的字节码将在运行时生成并载入当前的ClassLoader。
好处:
(1)不需要为真实主题写一个形式上完全一样的封装类,当主题接口中方法很多时,不用为每一个接口写一个代理方法,可以节省大量代码。
(2)提升系统灵活性,例如有些动态代理的生成方法可以在运行时指定代理类的执行逻辑。
a、JDK自带的动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkDbQueryHandler implements InvocationHandler {
IDBQuery real = null;
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(real==null)
real=new DBQuery();
return real;
}
}
public static IDBQuery createJdkProxy(){
IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(
ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class},
new JdkDbQueryHandler());
return jdkProxy;
}
b、CGLIB
public class CglibDbQueryInterceptor implements MethodInterceptor{
IDBQuery real =null;
public Object intercept() throws Throwable{
if(real==null)
real=new DBQuery();
return real.request();
}
}
public static IDBQuery createCglibProxy(){
Enhancer enhancer=new Enhancer();
enhancer.setCallback(new CglibDbQueryInterceptor()); //指定切入点,定义代理类逻辑
enhancer.setInterface(new Class[]{IDBQuery.class}); //指定实现的接口
IDBQuery cglibProxy=(IDBQuery)enhancer.create(); //生成代理类的实例
return cglibProxy;
}
c、javassit
public class JavassistDynDbQueryHandler implements MethodHandler{
IDBQuery real=null;
public Object invoke(Object arg0,Method arg1,Method arg2,Object[] arg3)
throws Throwable{
if(real==null)
real=new DBQuery();
return real.request();
}
}
public static IDBQuery createJavassistDynProxy() throws Exception{
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(new Class[]{IDBQuery.class});
Class proxyClass=proxyFactory.createClass();
IDBQuery javassistProxy = (IDBQuery) proxyClass.newInstance();
((ProxyObject)javassistProxy).setHandler(new JavassistDynDbQueryHandler());
return javassistProxy;
}