JDK动态代理和CGLIB代理

JDK代理

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


这里写图片描述

通过实现接口实现

通过动态代理,给普通的对象生成代理对象,对其中的方法进行前置和后置的处理
例如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方法对委托方法进行代理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值