Java动态代理
来源:互联网 发布:2017淘宝注册用户数 编辑:程序博客网 时间:2024/06/18 14:45
Java主要有两种代理,JDK和Cglib动态代理。
Java的JDK动态代理
一个接口
public interface Advice { public void before(); public void after(); }
有两个横切逻辑类,如下:
public class TimeAdvice implements Advice { long startTime; long endTime; @Override public void before() { startTime = System.nanoTime(); // 获取开始时间 System.out.println("开始计算程序运行时间"); } @Override public void after() { endTime = System.nanoTime(); // 获取结束时间 System.out.println("计算程序运行时间: " + (endTime - startTime) + "ns"); } }
public class ControlAdvice extends TimeAdvice { @Override public void before() { super.before(); System.out.println("提前 判断系统的权限 "); } @Override public void after() { super.after(); System.out.println("判断系统的权限 完毕"); } }
一个目标类,如下:
public interface SalaryInterface { public void doSalary(); } public class Salary implements SalaryInterface{ public void doSalary() { System.out.println("进行薪资计算的逻辑处理"); } }
实现最重要的代理类,这个类需要实现一个特定的接口。如下:
package com.test.javaproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /* * 每一个代理实例都必须指定一个调用处理器,代理对象调用方法时, * 该方法会指派到调用处理器的invoke()中去。代理的方法封装成 * invoke中的method对象,其中的参数封装成Object[]. */ public class MyProxy implements InvocationHandler{ private Object obj; // 希望被代理的对象 private Advice advice; //绑定代理对象 public Object bind(Object obj, Advice advice) { this.obj = obj; this.advice = advice; return Proxy.newProxyInstance( obj.getClass().getClassLoader(), // 类加载器 obj.getClass().getInterfaces(), // 创建目标类所需要使用的一组接口 this // 一个实现InvocationHandler的实例,用来整合横切与业务逻辑 ); } //实现代理 /* * method为方法名,args为代理实例某一方法的入参数组,而obj为所属的实例对象 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { advice.before(); result = method.invoke(obj, args); advice.after(); } catch (Exception e){ e.printStackTrace(); } return result; } }
进行测试如下:
/* * 效果一样 ControlAdvice adv1 = new ControlAdvice(); 但是这时候ControlAdvice还是在 * 继承接口Advice,如果去掉这样的写就会报错。 * 所以说它只能为接口创建代理实例 */ Advice adv1 = new ControlAdvice(); SalaryInterface p = new Salary(); MyProxy proxy = new MyProxy(); SalaryInterface y = (SalaryInterface)proxy.bind(p, adv1); y.doSalary();// 相当于调用proxy.invoke(proxy, "doSalary, null);
最终运行结果为:
开始计算程序运行时间 提前 判断系统的权限 进行薪资计算的逻辑处理 计算程序运行时间: 743454ns 判断系统的权限 完毕
可以看到实现了Advic接口的代理类都进行了运行。
* Java的CGLib动态代理*
CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑。
public class BookFacadeImpl { public void addBook() { System.out.println("增加图书方法。。。"); } }
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 使用cglib动态代理 */ public class BookFacadeCglib implements MethodInterceptor { private Object target; /** * 创建代理对象 * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 设置需要创建子类的类 // 回调方法 enhancer.setCallback(this); // 通过字节码技术动态创建子类实例 return enhancer.create(); } @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; } }
BookFacadeCglib cglib=new BookFacadeCglib(); BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl()); bookCglib.addBook();
最终运行的结果如下:
事物开始 增加图书方法。。。 事物结束
注意加入cglib和asm的jar包,如不加asm包会报出如下错误:
Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type
CGGlib创建的代理对象要比JDK的性能高很多,但是创建时所花费的时间却比JDK动态代理要多。所以对于singleton的代理对象或者具有实例池的代码,由于无须频繁创建代码对象,用CGLib比较合适。
也就是生命周期长的实例用CGLib比较合适。
0 0
- Java 代理,动态代理
- [Java] Java 动态代理
- java代理及动态代理
- java代理模式--动态代理
- Java静态代理、动态代理
- Java 代理之 动态代理
- Java 代理与动态代理
- java静态代理,动态代理
- 代理模式&java动态代理
- Java代理与动态代理
- Java静态代理动态代理
- JAVA代理模式--动态代理
- java 代理和动态代理
- JAVA动态代理 代理模式
- Java动态代理--jdk代理
- Java动态代理--cglib代理
- Java 代理与动态代理
- java代理模式-动态代理
- MJRefresh
- OpenCV之OpenCL介绍
- 移植rtmpdump(rtmpdump)到android
- mysql学习3-数据类型
- Java8系列之重新认识HashMap
- Java动态代理
- Android ANR
- HDU 2852
- 栈、队列面试题
- 回溯算法
- css3动画
- JS题
- iOS 耳机影响音频
- QOS-5 拥塞避免机制Congestion Avoidance