JDK,Cglib动态代理笔记

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,与cglib不同,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

默认状态下,Spring-AOP默认使用JDK动态代理,当需要代理的对象没有实现任何接口时,才使用cglib动态代理。cglib动态代理创建代理实例速度慢,但是运行速度快;JDK动态代理创建实例速度快,但是运行速度慢。如果实例是单例的,推荐使用cglib方式动态代理,反之则使用JDK方式进行动态代理。Spring的实例默认是单例,所以这时候使用cglib性能高。 

1.先写个接口

public interface Person {
    void run();
    String talk(String word);
}

2.实现接口

public class Man implements  Person {
    @Override
    public void run() {
        System.out.println("Man is running..");
    }

    @Override
    public String talk(String word) {
        System.out.println("man is talking:");
        return  word;
    }
}

3.JDK代理实现:

public class JDKProxy implements InvocationHandler {
    private Object targetObject;//需要被代理的对象

    public JDKProxy() {
    }

    /***
     *  获取代理对象
     * @param o 需要被代理的对象
     * @return 代理后的对象
     */
    public Object getProxyObject(Object o){
        this.targetObject = o;
        return Proxy.newProxyInstance(o.getClass().getClassLoader(),//ClassLoader loader:类加载器,定义了由哪个ClassLoader对象来生成代理对象进行加载
                o.getClass().getInterfaces(),//Class<?>[] interfaces:得到该对象实现全部的接口,这样便可以调用所有接口内的方法了。
                this::invoke);//InvocationHandler h:调用处理器,它是得到InvocationHandler接口的子类实例
    }

    /***
     *
     * @param proxy 代理对象,也就是Proxy.newProxyInstance()方法返回的对象,通常我们用不上它
     * @param method 表示当前被调用方法的反射对象
     * @param args 表示当前被调用方法的参数,当然如果这个调用是没有参数的,那么args是一个零长数组
     * @return   最后要说的是invoke()方法的返回值为Object类型,它表示当前被调用的方法的返回值,如果没有返回值的,invoke()返回的就必须是null了。
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result=null;
        System.out.println("Proxy start...");
        System.out.println("method name:"+method.getName());
        //执行前的逻辑
        result=method.invoke(targetObject, args);
        //执行后的逻辑
        System.out.println("Proxy end...");
        return result;
    }
}

cglib代理实现

public class CGLibProxy implements MethodInterceptor {
    
    private Object targetObject;//需要被代理的对象

    /***
     *  获取代理对象
     * @param obj 需要被代理的对象
     * @return 代理后的对象
     */
    public Object getProxyObject(Object obj) {
        this.targetObject = obj;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        Object proxyObj = enhancer.create();
        // 返回代理对象
        return proxyObj;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args,
                            MethodProxy methodProxy) throws Throwable {
        Object result=null;
        System.out.println("Proxy start...");
        System.out.println("method name:"+method.getName());
        //执行前的逻辑
        result=method.invoke(targetObject, args);
        //执行后的逻辑
        System.out.println("Proxy end...");
        return result;
        
    }
    
}

4.测试类

    public static void main(String[]args){
        Person manProxy=(Person)(new JDKProxy().getProxyObject(new Man()));
        manProxy.run();
        String talkStr= manProxy.talk("hello world");
        System.out.println(talkStr);
    }

DK代理是不需要第三方库支持,只需要JDK环境就可以进行代理,在使用cglib动态代理时,需要引入cglib的jar包,有两种方式,一是引入cglib.jar和asm.jar,二是引入cglib-nodep.jar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值