欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDK动态代理和CGLIB代理

程序员文章站 2022-06-18 11:10:21
...

JDK代理

参考
https://www.cnblogs.com/MOBIN/p/5597215.html


JDK动态代理和CGLIB代理

通过实现接口实现

通过动态代理,给普通的对象生成代理对象,对其中的方法进行前置和后置的处理
例如spring的事务


使用动态代理的五大步骤
1.通过实现InvocationHandler接口来自定义自己的InvocationHandler;

2.通过Proxy.getProxyClass获得动态代理类

3.通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)

4.通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入

5.通过代理对象调用目标方法


//接口
public interface MyBuyInterface {
    void buy(String goods);
}

//实现这这个接口,也就是后面需要代理的对象
public class MyBuyClass implements MyBuyInterface {

    @Override
    public void buy(String goods) {
        System.out.println("我买了 " + goods);
    }

}

//实现自己的InvocationHandler
//实现InvocationHander接口
public class MyInvocationHandler implements InvocationHandler{

    //需要被代理的对象
    private Object target;

    public MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //前置处理
        System.out.println(new Date());
        //这里是实际调用实际的方法
        Object res = method.invoke(target, args);
        //后置处理
        System.out.println("买完了");
        return res;
    }

}

//进行实际的调用
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        //方法一
        //获取代理类
        Class<?> proxyClass = Proxy.getProxyClass(MyBuyInterface.class.getClassLoader(), MyBuyInterface.class);
        //获取代理类的构造方法,传入InvocationHandler接口
        Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
        //通过构造方法创建代理对象,传入自定义invocationHandler
        MyBuyInterface obj = (MyBuyInterface) constructor.newInstance(new MyInvocationHandler(new MyBuyClass()));

        //调用方法,此时会调用自定义invocationHandler的invoke方法
        obj.buy("苹果");

        //方法二
        //上面的几步可以通过下面这个方法合并为一步
        MyBuyInterface oobbjj = (MyBuyInterface) Proxy.newProxyInstance(MyBuyInterface.class.getClassLoader(), new Class[] {MyBuyInterface.class}, new MyInvocationHandler(new MyBuyClass()));
        oobbjj.buy("梨子");
    }

运行结果

Tue Aug 28 12:15:37 CST 2018
我买了 苹果
买完了
Tue Aug 28 12:15:37 CST 2018
我买了 梨子
买完了

CGLIB代理

CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。

//自定义方法拦截器,实现MethodInterceptor 接口
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
        System.out.println(new Date());
        Object res = proxy.invokeSuper(obj, arg);
        System.out.println("买完了");
        return res;
    }

}

//进行调用
public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();  
        //设置父类
        enhancer.setSuperclass(MyBuyClass.class);  
        //设置方法拦截器
        enhancer.setCallback(new MyMethodInterceptor());  
        //生成代理类
        MyBuyClass myBuyClass = (MyBuyClass)enhancer.create();
        myBuyClass.buy("梨子");
    }

//运行结果
Tue Aug 28 13:37:38 CST 2018
我买了 梨子
买完了

代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理

相关标签: 代理 jdk cglib