关闭

Java AOP实现

标签: javaaopcglib动态代理javassist
355人阅读 评论(0) 收藏 举报
分类:

1. 业务代码

public interface CellPhone {
    void description(Integer sequence);
    void setVersion(String version);
}

public class IOS implements CellPhone {
    private String version;

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public IOS(){}

    public void description(Integer sequence) {
        System.out.println("{sequence="+sequence+",version="+this.version+"}");
    }
}

public class Android implements CellPhone {
    private String version;

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public Android(){}

    public void description(Integer sequence) {
        System.out.println("{sequence="+sequence+",version="+this.version+"}");
    }
}

1. 使用动态代理

实现代码:

public class CellPhoneProxy implements InvocationHandler{
    private Object obj;

    private CellPhoneProxy(Object obj){
        this.obj = obj;
    }

    @SuppressWarnings("unchecked")
    public static<T> T getProxyInstance(Class<T> clazz){
        Object target = null;
        try {
            target = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T)Proxy.newProxyInstance(clazz.getClassLoader(),
                                    clazz.getInterfaces(), new CellPhoneProxy(target));
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if(method.getName().equals("description"))
            System.out.print("call "+obj.getClass().getSimpleName()+"."+method.getName()+"():");
        else
            System.out.println("call "+obj.getClass().getSimpleName()+"."+method.getName()+"()");
        Object result = method.invoke(obj, args);
        return result;
    }
}

测试代码:

public void test(){
    /* Android */
    CellPhone bean = CellPhoneProxy.getProxyInstance(Android.class);
    bean.description(1);
    bean.setVersion("4.2.0");
    bean.description(2);

    /* IOS */
    bean = CellPhoneProxy.getProxyInstance(IOS.class);
    bean.description(1);
    bean.setVersion("7.2");
    bean.description(2);
}

2. 使用cglib

实现代码:

public class CellPhoneInterceptor implements MethodInterceptor{
    public Object intercept(Object target, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {    
        if(method.getName().equals("description"))
            System.out.print("call "+target.getClass().getSimpleName()+"."+method.getName()+"():");
        else
            System.out.println("call "+target.getClass().getSimpleName()+"."+method.getName()+"()"); 
        Object rev = proxy.invokeSuper(target, args);  
        return rev;   
    }
}

测试代码:

public void test(){
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(Android.class);
       enhancer.setCallback(new CellPhoneInterceptor());
       Android android = (Android)enhancer.create();
    android.description(1);
    android.setVersion("4.2.0");
    android.description(2);

    enhancer = new Enhancer();
    enhancer.setSuperclass(IOS.class);
       enhancer.setCallback(new CellPhoneInterceptor());
       IOS ios = (IOS)enhancer.create();
       ios.description(1);
       ios.setVersion("7.2");
       ios.description(2);
}

3. 使用javassit

实现代码:

public class CellPhoneTranslator implements Translator{

    /**
     * Class装载入JVM之前进行代码织入
     * 
     */
    public void onLoad(ClassPool pool, String className) throws NotFoundException,
            CannotCompileException {
        CtClass cc = pool.get(className);
        if(className.equals("edu.njupt.afly.aop.testclass.Android")){
            //description方法织入
            CtMethod description = cc.getDeclaredMethod("description");
            description.insertBefore("{System.out.println(\"call Android description\");}");
            //setVersion方法织入
            CtMethod setVersion = cc.getDeclaredMethod("description");
            setVersion.insertBefore("{System.out.println(\"call Android setVersion\");}");
        }else if(className.equals("edu.njupt.afly.aop.testclass.IOS")){
            //description方法织入
            CtMethod description = cc.getDeclaredMethod("description");
            description.insertBefore("{System.out.println(\"call IOS description\");}");
            //setVersion方法织入
            CtMethod setVersion = cc.getDeclaredMethod("description");
            setVersion.insertBefore("{System.out.println(\"call IOS setVersion\");}");
        }
    }

    public void start(ClassPool pool) throws NotFoundException,
            CannotCompileException {

    }

    public static void main(String[] args) {   
        final CellPhone android = new Android();
        final CellPhone mac = new IOS();
        android.setVersion("4.2.0");
        android.description(1);
        mac.setVersion("7.2");
        mac.description(2);
    }  
}

测试代码:

public void test(){
    //获取存放CtClass的容器ClassPool   
    ClassPool cp = ClassPool.getDefault();   
    //创建一个类加载器   
    Loader cl = new Loader();   
    //增加一个转换器   
    try {
        cl.addTranslator(cp, new CellPhoneTranslator());
    } catch (NotFoundException e) {
        e.printStackTrace();
    } catch (CannotCompileException e) {
        e.printStackTrace();
    }
    try {
        cl.run("edu.njupt.afly.aop.javassist.CellPhoneTranslator", null);
    } catch (Throwable e) {
        e.printStackTrace();
    }
}

4. 总结

  • 实现方式:动态代理使用java的反射机制,通过在运行期生成接口的代理子类来实现;cglib是利用字节码技术,在运行期实现一个目标类的子类,然后在子类中通过拦截的方式织入横切逻辑,其实现依赖于ASM;javassist也是利用字节码技术,但是javassit是在类加载阶段将横切逻辑织入进方法体内,所以其效率更好。
  • 特点:发射和cglib是在运行期实现横切逻辑的织入,所以其效率较低,但是胜在可以获得方法调用的参数和返回值,功能更强大;而javassist因为是在类加载阶段织入横切逻辑,所以其效率相较于前两种方式较高,但是无法获得调用参数和返回值,有局限性。

以上是个人理解,欢迎大家批评指正。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:27475次
    • 积分:574
    • 等级:
    • 排名:千里之外
    • 原创:24篇
    • 转载:1篇
    • 译文:0篇
    • 评论:25条
    文章分类
    最新评论