代理模式之Cglib代理浅谈

129 阅读2分钟

「这是我参与2022首次更文挑战的第31天,活动详情查看:2022首次更文挑战」。

一、什么是Cglib代理

静态代理和动态代理都要求目标对象是一个接口的实现类,但有时候我们就是一个单独的对象,并没有实现任何接口。这个时候就可以使用Cglib代理的方式实现代理,Cglib代理也叫子类代理,是通过在运行的过程中实现一个子类的对象,从而达到对目标对象的扩展的目的。

二、Cglib代理模式的实现

cglib的使用需要引入相应的jar包。

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

上述方式引入了cglib的包,以便于接下来使用cglib。

public class WholesaleShop003 {
    public void sell() {
        System.out.println("啤酒售卖价格2元");
    }
}

没有实现任何接口的批发商对象,售卖啤酒

public class ShopProxy003 implements MethodInterceptor {
    private Object target;

    public ShopProxy003(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        Enhancer en = new Enhancer();
        en.setSuperclass(target.getClass());
        en.setCallback(this);
        return en.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object invoke = method.invoke(target, args);
        System.out.println("跑腿费2元");
        return invoke;
    }
}

实现MethodInterceptor,需要实现intercept方法,这个就是对方法进行拦截然后进行增强。此外,需要编写一个获取代理对象的方法。

public static void main(String[] args) {
    WholesaleShop003 shop = new WholesaleShop003();
    WholesaleShop003 proxy = (WholesaleShop003)new ShopProxy003(shop).getProxyInstance();
    proxy.sell();
}

通过ShopProxy003获取代理对象,然后执行对象自身的方法,在被intercept后,成功进行了增强。如果对sell方法加上final或者static,方法的增强均会失效。 image.png

三、总结

Cglib可以在运行期扩展java类与实现java接口,在运行期间可以进行拦截。spring的aop就使用了cglib。

注意:

  1. 如果目标是单独的对象,那么目标对象不能是final的,因为cglib拦截过后会创建子类,如果是final的对象,会直接抛出异常。
  2. 目标对象的方法不能是final或者static的,无法实现增强效果。