Java AOP实现

原创 2015年07月06日 16:32:27

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因为是在类加载阶段织入横切逻辑,所以其效率相较于前两种方式较高,但是无法获得调用参数和返回值,有局限性。

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

相关文章推荐

Java实现AOP需要的jar包

  • 2016年09月23日 09:59
  • 14.41MB
  • 下载

java 动态代理实现AOP

  • 2012年05月17日 14:30
  • 139KB
  • 下载

java基础巩固笔记(4)-实现AOP功能的封装与配置的小框架

本文通过是动态代理实现的AOP功能的封装与配置的小框架.加深对动态代理和AOP编程的理解...

java 动态代理aop 实现日志记录

java动态代理实现针对的类要有实现接口 package com.example.aop; public interface BusinessService { public void log...

Java动态代理三--模拟AOP实现

以下案例模拟AOP实现 目录结构 接口PersonService package com.ljq.service; public interface PersonSer...

Java-----------类似spring的AOP框架的实现

android培训、java培训、期待与您交流!         这个是在上一个视频的基础上来进行是实现的。首先就是有一个BeanFactory来进行总的整合,在这个类里面有个方法getBean参数...

Java利用动态代理模拟实现Spring的AOP(面向切面编程)功能的小实践

本文主要是带领读者实现一个小例子,来模拟 Spring 框架的面向切面编程(AOP)。实现过程中用到了 Java 的动态代理。...

Java反射之JDK动态代理实现简单AOP

JDK动态代理实现简单AOP     JDK 动态代理是 java 反射的一个重要特性。它在某种方面为 java 提供了动态性的特性,给应用带来了无限的空间。大名鼎鼎的 Hessian 、 Sp...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java AOP实现
举报原因:
原因补充:

(最多只允许输入30个字)