JDK Proxy和CGLib

Spring 中的 aop
1, Spring 中的 aop 注入到容器中的 对象是动态代理对象,代理的类型分为jdkProxy 和 CglibAopProxy 线程 其中被代理的对象是一个实体类且没有实现接口的时候,使用的是 CglibAopProxy 代理,当被代理的对象是实现一个接口的时候,使用的是jdkProxy
在这里插入图片描述
动态代理生成类.jpg
在启动类上添加的注解 使用的是@EnableAspectJAutoProxy(proxyTargetClass = true),参数也可以决定生成的代理类型
java动态代理、 cglib动态代理 底层实现? 实现都是通过Java,操作字节码,创建的对象 Java > class > jvm
为什么Java动态代理必须是接口?因为动态代理实现类默认 继承了 proxy ,在Java中类是单继承,所以必须是实现接口

为什么Java动态代理必须是实现接口.jpg
在这里插入图片描述

jdk实现动态代理的核心必须实现InvocationHandler 接口


public class Test9 implements InvocationHandler {

    /**
     * 自定义接口类
     */
    static interface Car{
        void runing();
    }

    /**
     * 静态内部类
     */
    static class Bus implements Car{
        @Override
        public void runing() {
            System.out.println("bus ~~~ run~~");
        }
    }

    /**
     * 静态内部类
     */
    static class Taxi implements Car{
        @Override
        public void runing() {
            System.out.println("Taxi ~~~ run~~");
        }
    }



    /**
     * 代理对象
     */
    private Object target;

    /**
     * 获取到代理对象
     * @param target
     * @return
     */
    public  Object getInstance(Object target) {
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    /**
     * 实现代理
     * @param proxy  代理对象
     * @param method 代理方法
     * @param args 代理参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("动态代理前的代码~~~~");
        // 执行此方法前后可以进行自定义业务处理
        Object invoke = method.invoke(target, args);
        // 执行此方法后
        return invoke;
    }

    public static void main(String[] args) {
        // 执行jdkproxy
        Test9 test9 = new Test9();
        Car car = (Car) test9.getInstance(new Bus());
        car.runing();
    }
}

在上述代码中 Test9 类相当于一个 代理对象,想要成为代理对象需要实现 InvocationHandler 接口 . 然后重写 接口必须的getInstance() 方法

此外需要一个自定义的属性 用于 重写 invoke方法中的代理方法
getInstance() 方法中 三个参数分别代表了 proxy 代理对象,
method 代理方法, args 代理参数

当代理方法被阻塞的时候 .会重复 执行前面 代理类方法被调用前的代码.
在这里插入图片描述
在引入 CGLib前需要在 pom文件中加入以下依赖
在这里插入图片描述

java代码实现如下


    /**
     * 自定义接口类
     */
    static class Car{
        void runing(){
            System.out.println("this car is run ~~~~");
        }
    }

    static class CGLib implements MethodInterceptor {
        private Object target;
        // 自定义实现getInstance 方法
        public Object getInstance(Object target){
            this.target=target;
            // 使用增强器类
            Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass( this.target.getClass());
            // 设置回调
            enhancer.setCallback(this);
            return enhancer.create();
        }

		// 重写接口定义的方法
        @Override
        public Object intercept(Object o,
                                Method method,
                                Object[] objects,
                                MethodProxy methodProxy) throws Throwable {
            System.out.println("调用方法前的处理~~~~");
            // 进行代理的类的方法调用
            Object result = methodProxy.invokeSuper(o, objects);
            // 还可以进行剩下的业务逻辑处理
            return result;
        }
    }

    public static void main(String[] args) {
        Car instance = (Car) new CGLib().getInstance(new Car());
        instance.runing();
    }

CGLib 的区别是通过enhancer 将代理类设置为被代理类的子类 来实现代理.因此 被代理类不能被final 关键字修饰,否则无法代理类无法继承,

 如果被代理类 是final 修饰 则被报错 
  Cannot subclass final class com.example.userinfo.test.Test10$Car

lombok 的实现是反射嘛?
lombok 和反射完全没有关系, 反射是 程序在运行期间的一种自省 ,而lombok 实际上是在编译期间就完成了.

动态代理和静态代理的区别
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值