代理模式:aspectj静态代理和jdk,cglib的动态代理的对比

1.使用jdk的动态代理来增强接口实现类。

原理:使用Proxy类的newProxyInstance方法运行期通过反射动态的生成代理对象

优点:不需要修改具体的业务代码,动态的增强方法,降低耦合性。

缺点:代理的对象必须有接口实现。

代码如下:

接口:

package com.yellow.proxy.jdk;

public interface Iwork {
    public abstract void service();
}

实现类:

package com.yellow.proxy.jdk;

public class IworkImpl implements Iwork {
    public void service() {
        System.out.println("提供服务");
    }
}

 切面类:

package com.yellow.proxy.jdk;

public class Advices {
    public void log(){
        System.out.println("记录日志");
    }
    public void transaction(){
        System.out.println("事务操作");
    }
}

 

测试类:

package com.yellow.proxy.jdk;

import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {
    /**
     * 使用jdk的动态代理来增强接口实现类
     */
    @Test
    public void test1(){
        //创建目标对象
        Iwork iwork = new IworkImpl();

        //创建切面类
        Advices advices = new Advices();

        //创建代理对象
        Iwork iwork_proxy = (Iwork)Proxy.newProxyInstance(iwork.getClass().getClassLoader(), iwork.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                advices.log();
                Object invoke = method.invoke(iwork, args);
                advices.transaction();
                return invoke;

            }
        });

        //使用代理对象调用方法
        iwork_proxy.service();
    }

}

 

测试结果:

代理模式:aspectj静态代理和jdk,cglib的动态代理的对比_第1张图片

 

2.cglib动态代理。可以对jdk的动态代理作为补充。

原理:以创建目标类的子类来生成动态代理对象。

优点:不需要修改具体的业务代码,动态的增强方法,降低耦合性。

缺点:不能对final修饰的类,final修饰的方法或static的方法进行代理

代码如下:

目标类:

package com.yellow.proxy.cglib;

public class Work{
    public void service() {
        System.out.println("提供服务");
    }
}

切面类:

package com.yellow.proxy.cglib;

public class Advices {
    public void log(){
        System.out.println("记录日志");
    }
    public void transaction(){
        System.out.println("事务操作");
    }
}

测试类:

package com.yellow.proxy.cglib;

import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibTest {
    /**
     * 使用cglib的动态代理来增强目标类 将被代理的类(不能为final)作为父类,创建子类去增强
     */
    @Test
    public void test1(){

        //创建目标对象
        Work work = new Work();
        //增强的对象
        Advices advices = new Advices();
        //创建增强器
        Enhancer enhancer = new Enhancer();

        //设置目标类为父类
        enhancer.setSuperclass(Work.class);

        //设置回调(增强的具体体现)
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                advices.log();
                Object invoke = method.invoke(work, objects);
                advices.transaction();
                return invoke;
            }
        });

        //创建代理对象
        Work proxy_work = (Work) enhancer.create();
        proxy_work.service();
    }
}

测试结果:

代理模式:aspectj静态代理和jdk,cglib的动态代理的对比_第2张图片 

3.aspecj 静态代理 

原理:在编译期织入代码,编译成class文件

优点:可以增强任何类,任何方法,包括(final,static修饰)

缺点:需要使用aspecj提供的Ajc编译器来编译Aj文件。

注意:测试的时候需要配置Aspect的环境

安装AspectJ 可以去官网下载 https://www.eclipse.org/aspectj/downloads.php

下载完了就有一个可执行的jar包,就可以next安装

idea设置:

代理模式:aspectj静态代理和jdk,cglib的动态代理的对比_第3张图片

还要将idea编译方式修改为Aj,maven的pom文件配置坐标

    
            org.aspectj
            aspectjweaver
            1.8.13
        
        
            org.aspectj
            aspectjrt
            1.8.13
        

代码如下:

注意:测试环绕增强的时候,要和其他增强分开测试,否则会报异常

Error:(22, 0) ajc: circular advice precedence: can't determine precedence between two or more pieces of advice that apply to the same join point: method-call(void com.yellow.aspectj.Work.test())

AspectJ文件,可以理解为一个类:

package com.yellow.aspectj;

public aspect FristAspectj {
    //切入点
    pointcut mypointcut():call(* Work.test(..));

    //前置增强
    before(): mypointcut(){
        System.out.println("前置增强");
    }
    //最终增强
    after():mypointcut(){
        System.out.println("后置增强");
    }
    //异常增强
    after() throwing(Exception e): mypointcut(){
        System.out.println("异常增强了");
        e.printStackTrace();
    }

//    //环绕增强
//    Object around():mypointcut(){
//        System.out.println("环绕前");
//        Object proceed = proceed();
//        System.out.println("环绕后");
//        return proceed;
//    }



}

测试类:

注意:需要测试final 和static 修饰的方法的时候,最好使用maven clean一下项目,否侧会影响测试结果

package com.yellow.aspectj;

import java.io.IOException;

public class Work {

    public void test(){
        System.out.println("提供服务");
    }

    public static void main(String[] args) throws IOException {
        Work work = new Work();
        work.test();

    }

}

运行结果:

代理模式:aspectj静态代理和jdk,cglib的动态代理的对比_第4张图片

 

final修饰:

代理模式:aspectj静态代理和jdk,cglib的动态代理的对比_第5张图片

 

static修饰:

代理模式:aspectj静态代理和jdk,cglib的动态代理的对比_第6张图片

 

你可能感兴趣的:(快速入门demo)