java代理模式
java可以分为JDK动态代理和CGLIB代理。JDK动态代理只能对实现了接口的类生成代理,而不能针对类。CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些
JDK动态代理
package hong_liang.base;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxy {
public interface IHello {
void sayHello();
}
static void hello(String str){
System.out.println("111");
}
static class Hello implements IHello {
public void sayHello() {
System.out.println("Hello world!!");
}
}
// 自定义InvocationHandler
static class HWInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
public HWInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("------插入前置通知代码-------------");
// 执行相应的目标方法
Object rs = method.invoke(target, args);
System.out.println("------插入后置处理代码-------------");
return rs;
}
}
public static void main(String[] args) throws Exception {
// 生成$Proxy0的class文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// 获取动态代理类
Class<?> proxyClazz = Proxy.getProxyClass(IHello.class.getClassLoader(),IHello.class);
// 获得代理类的构造函数,并传入参数类型InvocationHandler.class
Constructor<?> constructor = proxyClazz.getConstructor(InvocationHandler.class);
// 通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入
IHello iHello = (IHello) constructor.newInstance(new HWInvocationHandler(new Hello()));
// 通过代理对象调用目标方法
iHello.sayHello();
//第二种方式动态调用
IHello iHello2 = (IHello) Proxy.newProxyInstance(IHello.class.getClassLoader(),new Class[]{IHello.class}, new HWInvocationHandler(new Hello()));
iHello2.sayHello();
}
}
CGLIB动态代理
package sunhongliang;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibTest {
public static void main(String[] args) {
CglibTs ct = new CglibTs();
ClassHasNoInterface chni = (ClassHasNoInterface) ct.getProxy(ClassHasNoInterface.class);
chni.method();
chni.function();
}
}
class ClassHasNoInterface {
public void method() {
System.out.println("建立自己的知识体系还是很重要的,尽管觉得麻烦");
}
public void function() {
System.out.println("如果我只停留在使用的别人开发的工具阶段,那么再过5年我也对不起程序员这个称呼");
}
}
class CglibTs implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class<?> clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(method.getName() + "执行之前做一些准备工作");
// 一不小心写成下面被注释一行代码了。 StackOverflowError
// Object result = method.invoke(obj, args);
Object result = proxy.invokeSuper(obj, args);
System.out.println(method.getName() + "执行之后做一些准备的工作");
return result;
}
}