第十二讲-AOP之proxy增强-cglib

第十二讲-AOP之proxy增强-cglib

使用Cglib作为代理的例子

package com.cherry.a12;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyDemo {
    static class Target{
        public void foo(){
            System.out.println("target foo...");
        }
    }

    public static void main(String[] args) {
        // 准备目标对象
        Target target = new Target();
        Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
            @Override             // 代理对象自己  代理类中执行的方法  方法执行时的参数   方法参数
            public Object intercept(Object p, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("before...");
                Object result = method.invoke(target, args);// 执行结果
                System.out.println("after...");
                return result;
            }
        });
        proxy.foo();
    }
}

运行结果如下:

before...
target foo...
after...

使用Cglib实现动态代理的特点:

  • 代理类和目标类是子父的关系(代理类是子类,目标类是父类)
  • 这也带来了一个问题,如果目标类使用了final关键字修饰,那么代理能成功吗?不行,例如将Target类改用final关键字修饰:
static final class Target{
    public void foo(){
        System.out.println("target foo...");
    }
}

则会抛出异常:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class com.cherry.a12.CglibProxyDemo$Target
  • 当然,如果目标类的方法使用final关键字修饰,那么使用cglib还是实现功能增强吗,则是不能的:
static class Target{
    public final void foo(){
        System.out.println("target foo...");
    }
}
target foo...

代理的本质就是对方法的重写,既然方法都不能被重写了,自然代理的增强功能也就失去了作用!

目前的Cglib使用的是反射机制来调用目标,但是Cglib还提供了MethodProxy避免发射调用目标方法,如下面的示例(需要的是目标对象):

Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
    @Override             // 代理对象自己  代理类中执行的方法  方法执行时的参数   方法参数
    public Object intercept(Object p, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("before...");
        //Object result = method.invoke(target, args);// 执行结果
        Object result = methodProxy.invoke(target, args);	// 使用的不是反射!
        System.out.println("after...");
        return result;
    }
});

运行如下:

before...
target foo...
after...

还有一种是调用invokeSuper()方法 --> 需要的是代理对象:

methodProxy.invokeSuper(p, args);
before...
target foo...
after...
posted @   LilyFlower  阅读(11)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示