读书人

面临AOP编程 一 动态代理

发布时间: 2012-12-23 11:28:15 作者: rapoo

面向AOP编程 一 动态代理

/** * JDK 实现的动态代理    打印日志切面类  */public class LogInvocationHandler implements InvocationHandler {public static void main(String[] args) {// 需要代理的接口,被代理类实现的多个接口都必须在这里定义Class[] proxyInterface = new Class[] { IBusiness.class,IBusiness2.class };// 构建AOP的Advice,这里需要如业务的实例LogInvocationHandler handler = new LogInvocationHandler(new Business());// 生成代理类的字节码加载器ClassLoader classLoader = LogInvocationHandler.class.getClassLoader();// 织入器,织入代码并生成代理类IBusiness2 proxyBusiness = (IBusiness2) Proxy.newProxyInstance(classLoader, proxyInterface, handler);//使用代理类的实例调用方法proxyBusiness.doSomeThing2();((IBusiness)proxyBusiness).doSomeThing();}private Object target;// 目标对象LogInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// 执行原有的逻辑Object rev = method.invoke(target, args);// 执行织入的日志,你可以控制那些方法执行切入逻辑if (method.getName().equals("doSomeThing2")) {System.out.println("记录日志");}return rev;}}interface IBusiness {public boolean doSomeThing();}interface IBusiness2 {public boolean doSomeThing2();}class Business implements IBusiness, IBusiness2 {public boolean doSomeThing() {System.out.println("执行业务逻辑");return false;}public boolean doSomeThing2() {System.out.println("执行业务逻辑2");return false;}}

动态代理的核心其实就是代理对象的生成,即Proxy.newProxyInstance(classLoader, proxyInterface, handler)

??? 动态代理在运行期通过接口动态生成代理类,这为其带来了一定的灵活性,
但这个灵活性却带来了两个问题,第一代理类必须实现一个接口,
如果没实现接口会抛出一个异常。第二性能影响,因为动态代理使用反射的机制实现的,

??? 首先反射肯定比直接调用要慢,经过测试大概每个代理类比静态代理多出10几毫秒的消耗。
??? 其次使用反射大量生成类文件可能引起Full GC造成性能影响,
?????? 因为字节码文件加载后会存放在JVM运行时区的方法区(或者叫持久代)中,
?????? 当方法区满的时候,会引起Full GC,所以当你大量使用动态代理时,
?????? 可以将持久代设置大一些,减少Full GC次数。

?

CgLib 实现动态代理

?

/** * Cglib是一个强大的,高性能的Code生成类库, * 它可以在运行期间扩展Java类和实现Java接口, * 它封装了Asm,所以使用Cglib前需要引入Asm的jar */public class LogIntercept implements MethodInterceptor{public static void main(String[] args) {//创建一个织入器Enhancer enhancer = new Enhancer();//设置父类enhancer.setSuperclass(Business.class);//设置需要织入的逻辑enhancer.setCallback(new LogIntercept());//使用织入器创建子类IBusiness2 newBusiness = (IBusiness2)enhancer.create();newBusiness.doSomeThing2();((IBusiness)newBusiness).doSomeThing();}public Object intercept(Object target, Method method, Object[] args,MethodProxy proxy) throws Throwable {//执行原有逻辑,注意这里是invokeSuperObject rev = proxy.invokeSuper(target, args);//执行织入的日志if (method.getName().equals("doSomeThing2")) {System.out.println("记录日志");}return rev;}}

读书人网 >编程

热点推荐