设计模式-代理模式
根据代理类是在运行前还是运行时指定,代理模式可以分为静态代理和动态代理;动态代理又可以根据实现方式不同分为:jdk动态代理、cglib动态代理,javassist动态代理。
jdk动态代理
jdk动态是基于反射实现的,只能代理有接口的类。代理的关键是实现InvocationHandler,被代理对象方法具体执行时,会通过InvocationHandler的invoke去执行,具体生成代理类需要依赖Proxy。
实例代码:
代理接口:
public interface CommonFeature {
String doBusiness(String name);
}
具体业务实现:
public class ConcreteService implements CommonFeature{
public String doBusiness(String name) {
return name+",你好";
}
}
代理类:
public class ServiceProxy implements InvocationHandler {
private Object proxyObject;
public ServiceProxy(Object proxyObject) {
this.proxyObject = proxyObject;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("业务前的准备处理,比如记录日志");
return method.invoke(this.proxyObject, args);
}
}
客户端:
public class Client {
public static void main(String[] args) {
ConcreteService service = new ConcreteService();
ServiceProxy serviceProxy = new ServiceProxy(service);
CommonFeature proxyInstance = (CommonFeature)Proxy.newProxyInstance(service.getClass().getClassLoader(),
new Class[] {CommonFeature.class},
serviceProxy);
System.out.println(proxyInstance.doBusiness("XX"));
}
}
输出结果如下图:

cglib动态代理
cglib相对于jdk代理不同的是:cglib底层是依赖ASM字节码框架直接操作字节码完成对原类型的扩展以生成代理类;cglib实现代理不强制要求被代理类实现接口;cglib使用继承的方式扩展被代理类的方法的功能,因此final的类不能被代理,final的方法不能被代理执行;
cglib的关键是MethodInterceptor和Enhancer,通过Enhancer操作字节码生成被代理类的子类,然后为代理类设置回调MethodInterceptor ,从而可以在执行时,先执行MethodInterceptor 的intercept,然后执行父类的相关方法。
实现实例:
被代理类如下
public class BusinessService {
public BusinessService() {
System.out.println("构造方法执行。。。。。");
}
public final void doSomething1(){
System.out.println("执行无法被代理的方法");
}
public void doSomething2(){
System.out.println("执行被代理方法");
}
}
实现的MethodInterceptor类如下
public class MyMethodInterceptor implements MethodInterceptor {
/**
*
* @param o 生成的代理对象
* @param method 被代理对象方法
* @param objects 方法参数
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("业务前的准备处理,比如记录日志");
return methodProxy.invokeSuper(o,objects);
}
}
客户端如下
public class Client2 {
public static void main(String[] args) {
MyMethodInterceptor myMethodInterceptor = new MyMethodInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(BusinessService.class);
enhancer.setCallback(myMethodInterceptor);
BusinessService proxy = (BusinessService)enhancer.create();
System.out.println("客户端执行doSomething1.................");
proxy.doSomething1();
System.out.println("客户端执行doSomething2.................");
proxy.doSomething2();
}
}
执行结果:

javassist生成代理类
javassist是一款操作java字节码的类库,同样也可以用它来实现代理,实现的方式有两种:第一种是直接使用官方提供util生成代理类(如代码实例);第二种是自己通过javassist的api去构造代理类(可以参考dubbo的api模块和common模块实现的代理)。
代码实例:
客户端
package lean.proxy;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
import java.lang.reflect.Method;
/**
* @author qingh.yxb
*/
public class Client3 {
public static void main(String[] args) throws Exception {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setSuperclass(BusinessService.class);
proxyFactory.setFilter(new MethodFilter() {
public boolean isHandled(Method method) {
return method.getName().equals("doSomething2");
}
});
Class c = proxyFactory.createClass();
BusinessService instance = (BusinessService)c.newInstance();
MethodHandler handler = new MethodHandler() {
public Object invoke(Object o, Method method, Method method1, Object[] objects) throws Throwable {
System.out.println("业务前的准备处理,比如记录日志");
return method1.invoke(o, objects);
}
};
((Proxy)instance).setHandler(handler);
System.out.println("javassist代理-客户端执行doSomething1.................");
instance.doSomething1();
System.out.println("javassist代理-客户端执行doSomething2.................");
instance.doSomething2();
}
}
执行结果如下图:


1370

被折叠的 条评论
为什么被折叠?



