欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-04 23:18:01
...

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
后置通知...
相关标签: 23种设计模式