004-Spring AOP源码分析

原理分析

CGLIb

java 复制代码
OrderService orderService = new OrderService();

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderService.class);
//如果是需要所有方法都执行的setCallback
//在setCallbacks 如果设置了多个Callback 那么必须setCallbackFilter
enhancer.setCallbacks(new Callback[]{
        new MethodInterceptor() {
        	//第一个参数是代理对象 官方文档上写明了 如果invoke传入o则发生循环调用
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("执行了代理内容1");
                return methodProxy.invoke(orderService, objects);
            }
        },
        new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("执行了代理内容2");
                return methodProxy.invoke(orderService, objects);
            }
        },

});
enhancer.setCallbackFilter(new CallbackFilter() {
    @Override
    public int accept(Method method) {
        //指这个方法所执行代理intercept 的下标
        return 1;
    }
});

OrderService orderServiceProxy = (OrderService) enhancer.create();
System.out.println(orderServiceProxy.getOrderId());

动态代理

java 复制代码
BillApi phoneBill = new PhoneBillImpl();

BillApi phoneBillProxy = (BillApi) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{BillApi.class}, new InvocationHandler() {
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("执行方法前代理");
        return method.invoke(phoneBill, objects);
    }
});

System.out.println(phoneBillProxy.getId());

Spring 统一封装

一个是继承,一个是实现,都有各自适用的场景

但是都是一个实例方法的增强

所以统一封装便于使用

java 复制代码
接口类代理
BillApi phoneBill = new PhoneBillImpl();

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(phoneBill);
proxyFactory.addAdvice(new MethodBeforeAdvice() {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行前代理");
    }
});
proxyFactory.addAdvice(new AfterReturningAdvice() {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行后代理");
    }
});
BillApi proxy = (BillApi)proxyFactory.getProxy();
proxy.userName();
java 复制代码
非接口代理:
OrderService orderService = new OrderService();

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(orderService);
proxyFactory.addAdvice(new MethodBeforeAdvice() {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行前代理");
    }
});
proxyFactory.addAdvice(new AfterReturningAdvice() {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行后代理");
    }
});

OrderService proxy = (OrderService)proxyFactory.getProxy();
proxy.getOrderId();

屏蔽了底层的代理工具的切换

抽象了代理方法Advice

不需要再手动调用:被代理类(原型)的方法

相关推荐
wang09077 分钟前
自己动手写一个spring之aop_1
java·后端·spring
神奇小汤圆21 分钟前
IDEA 运行报 Command line is too long?别慌,两招搞定(附原理)
后端
SelectDB42 分钟前
Apache Doris 4.1 全面增强 Iceberg:支持 UPDATE、MERGE INTO 与 Iceberg V3
后端
国科安芯43 分钟前
FreeRTOS RISC-V 浮点上下文切换移植:在 IAR 工程中完整保存 FPU 寄存器
java·开发语言·单片机·嵌入式硬件·算法·系统架构·risc-v
Conan在掘金1 小时前
ArkTS 进阶之道(13):ForEach 循环渲染边界——为啥 build 里不能写 for 循环
后端
deng12041 小时前
【Thread类的用法(1)-- Thread类的基本用法】
java·java-ee
妙码生花1 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(四十一):增加管理员账号管理接口
后端·go·gin
用户0678260743271 小时前
APP版本管理全链路(后端设计)
后端
suconnect2 小时前
Spring Boot接入企业RAG:文档切分、向量检索、权限过滤和答案溯源
java·spring boot·后端
weixin_BYSJ19872 小时前
springboot校园自习室管理小程序---附源码32142
java·javascript·spring boot·python·django·flask·php