Macros

给我一支烟!请所有烦恼都能过往如云烟!

导航

深入浅出 spring AOP (二)

有人问我,为什末使用CGLIB proxy而不使用JDK Dynamic Proxies,这和spring aop使用的原则相关。
1.使用AOP的时候,尽可能的使用接口,而不是使用具体的类,这样就可以使用JDK Dynamic Proxies,
如果目标类没有实现接口,spring使用CGLIB生成目标类的子类。
下面给个例子
接口类
package org.tatan.test;


    public interface Worker {
        void doSomeWork(int numOfTimes);
    }
    
目标类
package org.tatan.test;
public class WorkerBean implements Worker {

    public void doSomeWork(int numOfTimes) {
        for (int i = 0; i < numOfTimes; i++) {
            System.out.print("");
        }
    }
}
Advice执行流程
package org.tatan.test;
import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;


public class AroundAdvice implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
     
        Object returnValue = invocation.proceed();

        Method m = invocation.getMethod();
        Object target = invocation.getThis();
        Object[] args = invocation.getArguments();
        System.out.println("Executed method: " + m.getName());
        System.out.println("On object of type: " + target.getClass().getName());
        System.out.println("With arguments:");
        for (int i=0;i<args.length;i++) {
            System.out.println("---->" + args[i]);
        }
        System.out.println();
       
        return returnValue;
    }
}
运行
package org.tatan.test;

import org.springframework.aop.framework.ProxyFactory;

public class AOPExample2 {
    public static void main(String[] args) {
        Worker bean = getWorkerBean();
        bean.doSomeWork(100000000);
    }

    private static Worker getWorkerBean() {
        WorkerBean target = new WorkerBean();
        ProxyFactory pf = new ProxyFactory();
        pf.setTarget(target);
        pf.addAdvice(new AroundAdvice());
        pf.setInterfaces(new Class[]{Worker.class});

        return (Worker) pf.getProxy();
    }
}
如果调用了setInterfaces();就不要cglib了,使用JDK Dynamic Proxies,只是使用JDK Dynamic Proxies程序执行的效率比较低。
使用CGLIB的Frozen效率比标准的CGLIB效率高。
package org.tatan.test;

import org.springframework.aop.framework.ProxyFactory;

public class AOPExample2 {
    public static void main(String[] args) {
        Worker bean = getWorkerBean();
        bean.doSomeWork(100000000);
    }

    private static Worker getWorkerBean() {
        WorkerBean target = new WorkerBean();
        ProxyFactory pf = new ProxyFactory();
        pf.setTarget(target);
        pf.addAdvice(new AroundAdvice());
     //  pf.setInterfaces(new Class[]{Worker.class});
        pf.setFrozen(true);

        return (Worker) pf.getProxy();
    }
}
原则上使用CGLIB,因为既可以使用类,还可以使用接口,JDK proxy 只能代理口

2.目标类的方法不能是final的,因为spring要生成目标类的子类,任何要advised的方法都要overide,所以不允许final method。


原文链接:http://blogger.org.cn/blog/more.asp?name=hongrui&id=9971

posted on 2006-02-13 18:10  Macros  阅读(349)  评论(0)    收藏  举报