java代理,静态代理、jdk代理、cglib代理、Aspectj

 

我实在接触spring的时候才接触到代理这个东西的,一直想整理一下笔记。

什么是代理模式:代理模式是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能。简单来说就是要创建一个新的对象,我们通过这个新的代理对象来操作目标对象。

例如我们租房子,我们可以直接和房东谈,房东其实就是我们的目标对象。但是有时候房东没空理你,所以他们就委托一个中介公司来代他和我们谈,这时候中介公司就可能会搞小动作,例如水电费收贵点,房租收贵1000,这就是所谓的增强操作。

 

 

代理的实现有4种:静态代理、jdk代理、cglib代理、Aspectj

 

1、静态代理

静态代理其实就是你自己写一个代理对象的类。就像下面的 Intermediary 

package com.hongcheng.dubbo_api.producer;


/** 房东,一个接口 */
interface Landlord{
    /** 出租房子 */
    void rentHouse();
}


/** 包租婆,具体实现 */
class LandlordWoman implements Landlord{
    /** 出租房子 */
    @Override
    public void rentHouse(){
        System.out.println("包租婆   ====>   房子800租给你了");
    }
}

/**
 *  中介公司,这就是代理类
 * */
class Intermediary implements Landlord{
    private Landlord landlord;
    public Intermediary(Landlord landlord) {
        this.landlord = landlord;
    }
    /** 出租房子 */
    @Override
    public void rentHouse() {
        System.out.println("中介公司   ====>   房子1000出租,我要赚200");
        this.landlord.rentHouse();
    }
}


/**
 *  测试
 * */
public class StaticProxy {
    public static void main(String[] args) {
        // 要有一个包租婆
        Landlord landlordWoman = new LandlordWoman();
        // 包租婆委托给中介公司
        Intermediary intermediary = new Intermediary(landlordWoman);
        // 中介公司出租房子给各位韭菜
        intermediary.rentHouse();
    }
}

 

静态代理优点:

  1.   可以对目标类的每个方法都做不同的处理,进行更细致的处理。

静态代理缺点:

  1.   必须手动重写目标类的所有方法,如果目标类方法过多,编写会很麻烦。
  2.   如果目标类的方法修改了,代理类也必须同步修改,维护麻烦。

 

2、 jdk代理

jdk代理这是一种动态代理,不需要我们自己去撸这个一个代理类,由jdk的api来帮我们创建这个类,我们只是要设计一下要怎么代理就好

package com.hongcheng.dubbo_api;

import junit.framework.TestCase;

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

/** 房东,一个接口 */
interface Landlord{
    /** 出租房子 */
    void rentHouse();
}

/** 包租婆,具体实现 */
class LandlordWoman implements Landlord {
    /** 出租房子 */
    @Override
    public void rentHouse(){
        System.out.println("包租婆   ====>   房子800租给你了");
    }
}
/**
 *  测试
 * */
public class AppTest extends TestCase {

    public static void main(String[] args) throws IOException {
        /** 我们的目标对象 */
        LandlordWoman hongcheng = new LandlordWoman();
        /** 我们目标对象的类加载器 */
        ClassLoader classLoader = hongcheng.getClass().getClassLoader();
        /** 我们目标对象实现的接口 */
        Class[] interfaces = hongcheng.getClass().getInterfaces();
        /***
         * 创建代理对象
         * @param classLoader 类加载器,一般用我们目标对象的类加载器
         * @param interfaces 我们目标对象实现的接口
         * @param InvocationHandler 我们要对目标对象所有方法做的增强处理
         * */
        Object instance = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            /***
             * 我们对目标对象的所有方法做的增强处理。
             * @param proxy jdk帮我们创建的代理对象
             * @param method 我们自己的目标对象的方法
             * @param args 我们目标对象方法的调用参数
             * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理开始");
                System.out.println("中介公司   ====>   房子1000出租,我要赚200");
          // 这里要记住,invoke方法传入的对象是我们的目标对象,不是代理对象 Object invoke
= method.invoke(hongcheng); System.out.println("代理结束,结果===>" + invoke); return invoke; } }); Landlord hong = (Landlord)instance; hong.rentHouse(); // 这里阻塞程序是为了用工具将代理对象的class弄成.class文件 System.in.read(); } }

 

jdk代理优点:

  1.   只需要写一个对所有方法的增强处理就可以,jdk的api会自动处理所有方法,不管后面你怎么更改目标类,代理类的创建的代码都不用改变。

jdk代理缺点:

  1.     不能更细致的处理个别方法,所有方法的增强处理都是一样的。
  2.   目标类必须实现一个接口

 

让我们来看看jdk帮我们生成的代理对象是咋样的先:

$Proxy0 就是我们的代理对象:
特点:
继承Proxy类,实现了我们的Landlord接口
每个方法的调用实际上都是调用我们写的那个匿名内部类
InvocationHandler 的invoke方法,将我们原本的方法和参数传入。
package com.hongcheng.dubbo_api;

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

final class $Proxy0 extends Proxy implements Landlord {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) {
        super(var1);
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.hongcheng.dubbo_api.Landlord").getMethod("rentHouse");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }

    public final boolean equals(Object var1) {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void rentHouse() {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
}

 

匿名内部类,增强方法的实现。

package com.hongcheng.dubbo_api;

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

final class AppTest$1 implements InvocationHandler {
    AppTest$1(LandlordWoman var1) {
        this.val$hongcheng = var1;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理开始");
        System.out.println("中介公司   ====>   房子1000出租,我要赚200");
        Object invoke = method.invoke(this.val$hongcheng);
        System.out.println("代理结束,结果===>" + invoke);
        return invoke;
    }
}

 

 

3、cglib代理

cglib 就是  Code Generator Library  ,是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架,同样使用CGLIB来代理单端(多对一和一对一)关联(延迟提取集合使用的另一种机制)。

要用cglib需要引入jar包,这里我用maven


    cglib
    cglib
    3.3.0

 

package com.hongcheng.dubbo_api;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.io.IOException;
import java.lang.reflect.Method;
/** 房东,一个接口 */
interface Landlord{
    /** 出租房子 */
    void rentHouse();
}
/** 包租婆,具体实现 */
class LandlordWoman implements Landlord {
    /** 出租房子 */
    @Override
    public void rentHouse(){
        System.out.println("包租婆   ====>   房子800租给你了");
    }
    public final void finalMethod(){
        System.out.println("finalMethod   ====>    执行了");
    }
    public static void staticMethod(){
        System.out.println("staticMethod   ====>    执行了");
    }
    public void privateMethod1(){
        System.out.println("privateMethod1   ====>    执行了");
        this.privateMethod2();
    }
    private void privateMethod2(){
        System.out.println("privateMethod2   ====>    执行了");
    }
}
/***
 *  测试
 * */
public class CglibProxy {
    public static void main(String[] args) throws IOException {
        // 一个很重要的对象,用来生成代理对象,翻译过来就是“增强器”,和jdk代理的Proxy类似功能
        Enhancer enhancer = new Enhancer();
        // 设置代理对象的父类,这是必须步骤
        enhancer.setSuperclass(LandlordWoman.class);
        // 设置回调,其实就是增强处理对象,每次调用代理的方法,都会回调调用intercept方法
        enhancer.setCallback(new MethodInterceptor() {
            /**
             * @param proxyObj 代理对象
             * @param method 目标类的方法
             * @param args 方法的参数
             * @param methodProxy 代理对象的方法
             * */
            @Override
            public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("代理开始");
                System.out.println("中介公司   ====>   房子1000出租,我要赚200");
                /**
                 *  methodProxy.invokeSuper(proxyObj, args);
                 *  这种方法使用的是代理对象的方法调用,传入的也是代理对象,但最后还是调用我们自己的目标方法
                 * */
                Object invoke = methodProxy.invokeSuper(proxyObj, args);
                /**
                 *  method.invoke(new LandlordWoman(), args);
                 *  这种方法使用的是我们目标对象的方法调用,传入的是目标对象,需要自己传入一个目标类的实例
                 * */
//                Object invoke2 = method.invoke(new LandlordWoman(), args);
                System.out.println("代理结束,结果===>" + invoke);
                return invoke;
            }
        });
        // 创建代理对象
        LandlordWoman proxy= (LandlordWoman)  enhancer.create();
        proxy.rentHouse();
        proxy.finalMethod();
        proxy.privateMethod1();
        proxy.staticMethod();
        // 这里阻塞程序是为了用工具将代理对象的class弄成.class文件
        System.in.read();
    }
}

 

cglib代理优点:

  1.   只需要写一个对所有方法的增强处理就可以,cglib的api会自动处理所有方法,不管后面你怎么更改目标类,代理类的创建的代码都不用改变。
  2.   目标类可以不实现任务接口。
  3.        Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类,性能上比较好

cglib代理缺点:

  1.     不能更细致的处理个别方法,所有方法的增强处理都是一样的。
  2.   目标类必须实现一个接口
  3.        代理的类不能为final,否则报错
  4.        目标对象的方法如果为final或static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

看看他生成后的代理对象内容是怎样,代码有点长

代理对象是直接继承自我们的目标对象的。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.hongcheng.dubbo_api;

import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class LandlordWoman$$EnhancerByCGLIB$$df42a67d extends LandlordWoman implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$rentHouse$0$Method;
    private static final MethodProxy CGLIB$rentHouse$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$privateMethod1$1$Method;
    private static final MethodProxy CGLIB$privateMethod1$1$Proxy;
    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    public LandlordWoman$$EnhancerByCGLIB$$df42a67d() {
        CGLIB$BIND_CALLBACKS(this);
    }

    static {
        CGLIB$STATICHOOK1();
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        LandlordWoman$$EnhancerByCGLIB$$df42a67d var10000 = new LandlordWoman$$EnhancerByCGLIB$$df42a67d;
        switch(var1.length) {
        case 0:
            var10000.();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        LandlordWoman$$EnhancerByCGLIB$$df42a67d var10000 = new LandlordWoman$$EnhancerByCGLIB$$df42a67d();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        LandlordWoman$$EnhancerByCGLIB$$df42a67d var10000 = new LandlordWoman$$EnhancerByCGLIB$$df42a67d();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }

    public final void rentHouse() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$rentHouse$0$Method, CGLIB$emptyArgs, CGLIB$rentHouse$0$Proxy);
        } else {
            super.rentHouse();
        }
    }

    public final void privateMethod1() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$privateMethod1$1$Method, CGLIB$emptyArgs, CGLIB$privateMethod1$1$Proxy);
        } else {
            super.privateMethod1();
        }
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    final int CGLIB$hashCode$4() {
        return super.hashCode();
    }

    final boolean CGLIB$equals$2(Object var1) {
        return super.equals(var1);
    }

    final Object CGLIB$clone$5() throws CloneNotSupportedException {
        return super.clone();
    }

    final String CGLIB$toString$3() {
        return super.toString();
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -1702390808:
            if (var10000.equals("privateMethod1()V")) {
                return CGLIB$privateMethod1$1$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$5$Proxy;
            }
            break;
        case 1194948270:
            if (var10000.equals("rentHouse()V")) {
                return CGLIB$rentHouse$0$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$2$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$3$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$4$Proxy;
            }
        }

        return null;
    }

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.hongcheng.dubbo_api.LandlordWoman$$EnhancerByCGLIB$$df42a67d");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
        var10000 = ReflectUtils.findMethods(new String[]{"rentHouse", "()V", "privateMethod1", "()V"}, (var1 = Class.forName("com.hongcheng.dubbo_api.LandlordWoman")).getDeclaredMethods());
        CGLIB$rentHouse$0$Method = var10000[0];
        CGLIB$rentHouse$0$Proxy = MethodProxy.create(var1, var0, "()V", "rentHouse", "CGLIB$rentHouse$0");
        CGLIB$privateMethod1$1$Method = var10000[1];
        CGLIB$privateMethod1$1$Proxy = MethodProxy.create(var1, var0, "()V", "privateMethod1", "CGLIB$privateMethod1$1");
    }

    final void CGLIB$rentHouse$0() {
        super.rentHouse();
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        LandlordWoman$$EnhancerByCGLIB$$df42a67d var1 = (LandlordWoman$$EnhancerByCGLIB$$df42a67d)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    final void CGLIB$privateMethod1$1() {
        super.privateMethod1();
    }
}

 

增强内部类的代码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.hongcheng.dubbo_api;

import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

final class CglibProxy$1 implements MethodInterceptor {
    CglibProxy$1() {
    }

    public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理开始");
        System.out.println("中介公司   ====>   房子1000出租,我要赚200");
        Object invoke = methodProxy.invokeSuper(proxyObj, args);
        System.out.println("代理结束,结果===>" + invoke);
        return invoke;
    }
}

 

 

在Spring的AOP编程中:
  如果加入容器的目标对象有实现接口,用JDK代理
  如果目标对象没有实现接口,用Cglib代理

  

4、Aspectj

Aspectj实际上他是一种静态代理,因为Aspectj是在编译代码的时候,将你的增强代码写入你的业务代码中,而不是去创建一个代理类。

 

  1. Aspectj并不是动态的在运行时生成代理类,而是在编译的时候就植入代码到class文件
  2. 由于是静态织入的,所以性能相对来说比较好
  3. Aspectj不受类的特殊限制,不管方法是private、或者static、或者final的,都可以代理
  4. Aspectj不会代理除了限定方法之外任何其他诸如toString(),clone()等方法

Aspectj的使用方法我实在是找不到,等以后找到了再补上吧

 

注意,像我们下面这种常常在spring中写的aop代码,使用的是jdk代理或者cglib代理,虽然用了Aspectj的注解,但仍然用的是jdk动态代理,或者cglib动态代理。

//声明这是一个组件
@Component
//声明这是一个切面Bean
@Aspect
@Slf4j
public class ServiceAspect {

    //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
    @Pointcut("execution(* com.hdj.learn.spring.aop.service..*(..))")
    public void aspect() {
    }

    /*
     * 配置前置通知,使用在方法aspect()上注册的切入点
     * 同时接受JoinPoint切入点对象,可以没有该参数
     */
    @Before("aspect()")
    public void before(JoinPoint joinPoint) {
        log.info("before " + joinPoint);
    }

    //配置后置通知,使用在方法aspect()上注册的切入点
    @After("aspect()")
    public void after(JoinPoint joinPoint) {
        log.info("after " + joinPoint);
    }

    //配置环绕通知,使用在方法aspect()上注册的切入点
    @Around("aspect()")
    public void around(JoinPoint joinPoint) {
        long start = System.currentTimeMillis();
        try {
            ((ProceedingJoinPoint) joinPoint).proceed();
            long end = System.currentTimeMillis();
            log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
        } catch (Throwable e) {
            long end = System.currentTimeMillis();
            log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
        }
    }

    //配置后置返回通知,使用在方法aspect()上注册的切入点
    @AfterReturning("aspect()")
    public void afterReturn(JoinPoint joinPoint) {
        log.info("afterReturn " + joinPoint);
    }

    //配置抛出异常后通知,使用在方法aspect()上注册的切入点
    @AfterThrowing(pointcut = "aspect()", throwing = "ex")
    public void afterThrow(JoinPoint joinPoint, Exception ex) {
        log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());
    }

}

 

关于怎么获取动态代理生成的class对象的.class文件,参考下面这两篇文章吧:

https://www.cnblogs.com/dengrong/p/10622594.html

http://www.mamicode.com/info-detail-2242036.html

 

注意看怎么使用       java -classpath sa-jdi.jar "sun.jvm.hotspot.HSDB"      和         jps -l      就行了,其他方法使用了,都没卵用,就HSDB这个东西可以生成class文件

 

你可能感兴趣的:(java代理,静态代理、jdk代理、cglib代理、Aspectj)