本文共 3006 字,大约阅读时间需要 10 分钟。
可以参看我的另外一篇博客,了解一下静态代理和动态代理:
JDK动态代理只能对实现了接口的类生成代理,而不能针对类;实现InvocationHandler接口,重写invoke()方法。
模拟链家找房子
1. 接口
定义一个方法,searchHouse(),找房子
/** * 接口 * @author 75736 * */public interface Person { void searchHouse(); }
2. 目标类
目标类实现接口,重写接口方法
/** * 目标类 * 实现接口 * @author 75736 * */public class Master implements Person { @Override public void searchHouse() { System.out.println("找房子"); }}
3. 代理类
代理类持有对目标对象的引用
/** * 代理类 * 持有目标类的引用 * @author 75736 * */public class HomeLink implements InvocationHandler{ private Person target; // 代理对象 /** * 初始化代理对象 * @param target * @return */ public Object getInstance(Person target){ this.target = target; Class clazz = target.getClass(); // static Object newProxyInstance(ClassLoader loader, Class [] interfaces, InvocationHandler h) // loader:指明代理对象使用哪个类加载器,代理类的类加载器 // interfaces:用来指明生成哪个对象的代理对象,通过接口指定,代理类实现的接口 // h:用来指明产生的这个代理对象要做什么事情,代理对象 Object obj = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); return obj; } @Override public Object invoke(Object obj, Method method, Object[] args) throws Throwable { System.out.println("我是链家,我帮别人找房子.."); // invoke(obj, args) // target:也就是被代理类的对象 // args:方法中的参数 method.invoke(target, args); System.out.println("我是链家,已经找完了.."); return null; }}
4. 测试
public class TestSearchHouse { public static void main(String[] args) { // 获取代理对象实例 Person person = (Person) new HomeLink().getInstance(new Master()); person.searchHouse(); }}
CGLIB是针对类实现代理,其原理是通过目标类的字节码为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
1. 目标类
/** * 目标类 * 没有可实现的父接口 * @author 75736 * */public class Master{ public void searchHouse() { System.out.println("找房子"); }}
2. 代理类
/** * 代理类 * 原理: 通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑 * * @author 75736 * */public class HomeLink implements MethodInterceptor { // net.sf.cglib.proxy.Enhancer:主要增强类,通过字节码技术动态创建委托类的子类实例; private Enhancer enhancer = new Enhancer(); /** * 获取代理对象 * * @param clazz * @return */ public Object getProxy(Class clazz) { // 进行代理,设置需要创建子类的类 enhancer.setSuperclass(clazz); // 设置织入逻辑 enhancer.setCallback(this); // 生成代理实例,通过字节码技术动态创建子类实例 return enhancer.create(); } /** * 实现MethodInterceptor接口方法 实现具体拦截处理 * @param obj:动态生成的代理对象 * @param method : 实际调用的方法 * @param args:调用方法入参 * @param proxy:java Method类的代理类,可以实现委托类对象的方法的调用 */ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("前置代理"); // 通过代理类调用父类中的方法 Object result = proxy.invokeSuper(obj, args); System.out.println("后置代理"); return result; }}
3. 测试
public class TestSearchHouse { public static void main(String[] args) { HomeLink proxy = new HomeLink(); // 通过生成子类的方式创建代理类 Master proxyImp = (Master) proxy.getProxy(Master.class); proxyImp.searchHouse(); // 调用intercept方法 }}
转载地址:http://hsqen.baihongyu.com/