10. 23种经典设计模式-23-代理模式扩展-cglib

1. cglib 代理

  • Cglib 代理也叫子类代理, 它是在内存中创建一个子类对象,从而实现对目标对象的功能扩展.
  • Cglib 的底层是通过字节码处理框架ASM来转换字节码并生成新的子类

1.1 注意事项

  • 代理的类不能使用final 修饰
  • 不能代理目标对象中被final 或 static 的方法, 因为cglib是通过拦截器机制实现的.

1.2 cglib 应用

  • cglib 被广泛用于各种Aop框架中, 如Sring的AOP 机制.
  • Spring AOP 动态代理实现逻辑:
    • 如果目标对象实现了接口, 那么使用JDK动态代理方式创建代理对象
    • 如果目标对象没有实现任何接口,那么使用cglib方式创建代理对象

2. cglib 动态代理

2.1 测试类图

  • MethodInvoker: 是cglib包下的接口, net.sf.cglib.proxy.MethodInterceptor
  • CglibProxy: 代理方法处理器, 类似于jdk动态代理的InvocationHandler

[外链图片转存失败(img-025VRukv-1566895017143)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-proxy-02.png)]

2.2 引入cglib 依赖

使用cglib 需要引入cglib 和 asm 包, 需要注意的是cglib 和 asm 包具有兼容性. 笔者用cglib3.0 测试有冲突, 所以切换回了cglib 2.2

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

<dependency>
    <groupId>asm</groupId>
    <artifactId>asm-commons</artifactId>
    <version>3.3.1</version>
</dependency>

2.3 被代理类

定义一个不实现任何接口的业务类

public class Hello {

    public void sayHello() {
        System.out.println("do method --> " + getClass().getName() + ".sayHello");
    }

    public void sayHi() {
        System.out.println("do method --> " + getClass().getName() + ".sayHi");
    }
}

2.3 cglib 动态方法处理器

和JDK动态代理类似, cglib 也需要实现一个目标方法代理处理器:

  • 实现接口MethodInterceptor, 并实现其intercept 方法
  • 提供获取动态代理对象的方法getProxyInstance(), 返回代理对象

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {

    // 被代理对象
    private Object target;

    public CglibProxy(Object object) {
        this.target = object;
    }

    // 获取动态代理对象
    public <T> T getProxyInstance() {

        // 1. 创建工具类
        Enhancer enhancer = new Enhancer();

        // 2. 设置父类
        enhancer.setSuperclass(target.getClass());

        // 3. 设置回调函数
        enhancer.setCallback(this);

        // 4. 创建子类对象, 即代理对象
        return (T) enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        // 执行目标方法前,可做一些预处理操作
        System.out.println("前置通知...");

        // 执行目标方法
        Object result = method.invoke(target, args);

        // 执行目标方法后, 可做一些清理工作
        System.out.println("后置通知...");

        // 返回结果
        return result;
    }
}

2.4 测试

@Test
public void test_cglib(){
    // 创建被代理对象
    Hello targetService = new Hello();

    // 创建代理对象
    Hello proxy =  new CglibProxy(targetService).getProxyInstance();

    // 执行请求
    proxy.sayHello();

    System.out.println("\n************************************************\n");

    proxy.sayHi();
}

2.5 测试输出

前置通知...
do method --> org.zongf.learn.design.pattern.proxy.Hello.sayHello
后置通知...

************************************************

前置通知...
do method --> org.zongf.learn.design.pattern.proxy.Hello.sayHi
后置通知...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值