Spring AOP:Java动态代理和CGlib

JDK动态代理设计模式

核心类:InvocationHandlerProxy。只能代理接口。

Java动态代理核心代码

/**
 * Java动态代理
 *
 * @Author YangXuyue
 * @Date 2018/09/17 23:46
 */
public class MyInvocationHandler implements InvocationHandler {

    /**
     * 执行方法的对象实例
     */
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    
    // proxy是最终生成的代理类,一般不会用到
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();

        Object object = method.invoke(target, args);

        System.out.println("方法:" + method.getName() + "执行了:" + (System.currentTimeMillis() - start) + " ms");

        return object;
    }

    // 获取代理实例
    public static Object proxy(Object target) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), new MyInvocationHandler(target));
    }
}

测试

        Waiter waiter = new NaiveWaiter();
        Waiter proxy = (Waiter) MyInvocationHandler.proxy(waiter);
        // 在执行以下方法的时候,这些方法都已经被增强了!
        proxy.sayHello("yangxuyue");
        proxy.sayBye("yangxuyue");

在动态代理的invoke方法里边,在原有方法的调用前后“织入”了我们的代码。其实这就是AOP中横切的过程,代理对象中在方法调用前后“植入”自己写的通用代码其实就是AOP中织入的过程!这个织入的代码也就是横切逻辑,织入代码的过程其实就是在原有的方法前后增强原方法的过程!这种技术手段就是AOP

CGLib

CGLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势的织入横切逻辑。

pom.xml

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.8</version>
        </dependency>

核心类

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

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    // object:目标类的实例 method:目标类方法的反射对象 args:方法的动态参数 proxy:代理类实例
    // intercept(Object, Method, Object[], MethodProxy) 拦截所有目标类的调用
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        long start = System.currentTimeMillis();

        Object result = proxy.invokeSuper(object, args);

        System.out.println(result);

        System.out.println("方法:" + method.getName() + "执行了:" + (System.currentTimeMillis() - start) + " ms");

        return object;
    }
}

测试

        CglibProxy proxy = new CglibProxy();
        VoiceBean bean = (VoiceBean) proxy.getProxy(VoiceBean.class);
        bean.saySomething();

代理类的类名字

 VoiceBean$$EnhancerByCGLIB$$a8907e36
原文地址:https://www.cnblogs.com/yang21/p/9970199.html