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

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

AOP的四种主要Java实现方式

据统计,目前与AOP相关的项目已达近百种,而基于Java的AOP实现机制也有二十多种,以下所列举的是商业上得到成熟应用的几种基于Java的AOP的实现机制。 AspectJ A...
  • q1054261752
  • q1054261752
  • 2016年08月13日 13:12
  • 3572

spring AOP 之 注解 配置实现(附 Java 代码实例)

导入类扫描的注解解析器 命名空间:xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=...
  • qq_27093465
  • qq_27093465
  • 2016年11月28日 18:16
  • 1769

Asm实现静态AOP的两种方式-生成java-proxy类

AOP静态生成Java proxy  静态AOP基于java agent方式加载 java-javaagent:myagent.jar    动态AOP是通过java动态代理或者字节码增强技术...
  • yongfeng596
  • yongfeng596
  • 2016年11月09日 21:33
  • 1092

Java实现AOP需要的jar包

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

java 动态代理实现AOP

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

使用java动态代理技术实现简单的AOP切面编程实例

  • 2017年03月05日 18:15
  • 14KB
  • 下载

Java编程中使用动态代理实现AOP功能(附项目设计实例)

  • 2013年08月29日 00:40
  • 227KB
  • 下载

java基础知识学习之代理深入学习(用动态代理实现AOP,FacotryBean)

1.代理的概念与作用 程序中的代理 能为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等; 编写一个与目标类具有相同接口的代理...
  • u014401141
  • u014401141
  • 2017年04月23日 15:42
  • 186

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

android培训、java培训、期待与您交流!         这个是在上一个视频的基础上来进行是实现的。首先就是有一个BeanFactory来进行总的整合,在这个类里面有个方法getBean参数...
  • ayzhnau2009
  • ayzhnau2009
  • 2012年03月25日 00:54
  • 186

Java实现简单的AOP(一)

AOP编程是面向切面编程,说白了,一段代码的执行归根结底是方法的执行,当一个系统写好之后,往往需要新的功能或者添加一些新的操作,这些新的功能又是一些方法,这些方法需要嵌入到原来的系统中,让他们在系统原...
  • yizhenn
  • yizhenn
  • 2016年08月11日 14:02
  • 96
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java AOP实现
举报原因:
原因补充:

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