(十四)Spring之回顾代理模式


Spring学习目录

上一篇:(十三)Spring之JdbcTemplate

下一篇:(十五)Spring之面向切面编程AOP

回顾代理模式

参考:代理模式Proxy Pattern
不用JDK的动态代理,手写JDK动态代理

动态代理常用技术

在程序运行阶段,在内存中动态生成代理类,被称为动态代理,目的是为了减少代理类的数量。解决代码复用的问题。
在内存当中动态生成类的技术常见的包括:

  • JDK动态代理技术:只能代理接口。参考代理模式Proxy Pattern
  • CGLIB动态代理技术:CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。它既可以代理接口,又可以代理类,底层是通过继承的方式实现的。性能比JDK动态代理要好。(底层有一个小而快的字节码处理框架ASM。)
  • Javassist动态代理技术:Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。
    参考动态生成类–javassist的使用

CGLIB动态代理技术

CGLIB既可以代理接口,又可以代理类。底层采用继承的方式实现。所以被代理的目标类不能使用final修饰。
使用CGLIB,需要引入它的依赖:

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

使用CGLIB代理类
创建一个目标类:

/**
 *  目标类,不是接口了
 */
public class TargetClass{

    public void sayHi(){
        System.out.println("Hi,动态 CGLEIB proxy");
    }
}

创建一个调用处理器类:
在CGLIB当中不是InvocationHandler接口,是方法拦截器接口:MethodInterceptor
实现的不是invoke方法了,是intercept方法
intercept有一个目标对象的值,所以这个类不需要依赖目标对象了
intercept方法有四个参数:

  • target:目标对象

  • method:目标方法

  • objects:目标方法参数

  • methodProxy:代理方法

public class ProxyClass implements MethodInterceptor {



    /**
     *
     * @param target 目标对象
     * @param method 目标方法
     * @param objects 目标方法参数
     * @param methodProxy 代理方法
     * @return 代理类
     * @throws Throwable
     */
    @Override
    public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //方法调用之前功能增强
        System.out.println("目标方法执行前。。。。");
        Object result = methodProxy.invokeSuper(target,objects);//该方法真正调用目标方法
        //方法调用之后功能增强
        System.out.println("目标方法执行后。。。。");
        return result;
    }
}

编写测试程序:
使用CGLIB在内存中为目标类生成代理类,并创建对象,有以下几个步骤:

  • 1.创建字节码增强器对象Enhancer
    这个对象是CGLIB库当中的核心对象,需要依靠它来生成代理类

  • 2.调用setSuperclass方法设置目标类/接口

  • 3.调用setCallback方法设置回调(等同于JDK动态代理当中的调用处理器InvocationHandler)

  • 4.调用create方法创建代理对象
    这一步会做两件事:

    • 其一:在内存中生成目标/接口的子类,其实就是代理类的字节码。
    • 其二:创建代理对象
public class Client {
    public static void main(String[] args) {
        //1.创建字节码增强器对象
        Enhancer enhancer = new Enhancer();
        //2.设置目标类/接口
        enhancer.setSuperclass(TargetClass.class);
        //3.设置回调(等同于JDK动态代理当中的调用处理器InvocationHandler)
        enhancer.setCallback(new ProxyClass());
        //4.创建代理对象
        TargetClass targetClass = (TargetClass)enhancer.create();
        targetClass.sayHi();
    }
}

运行程序:出现错误
请添加图片描述
原因是jdk8版本之后有了java.base这个包,jdk8版本之前没有,导致找不到。
需要加这两个参数
–add-opens java.base/java.lang=ALL-UNNAMED
–add-opens java.base/sun.net.util=ALL-UNNAMED
第一步:点击右上方进行编辑配置
在这里插入图片描述
第二步:点击修改选项,勾选添加VM选项
在这里插入图片描述
第三步:添加两个参数,保存
请添加图片描述
再次运行:运行成功
请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆亦何为

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值