讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

Seko
Seko

AI短剧一键生成成片

立刻MV
立刻MV

低成本歌曲 MV、视频生成

剧云
剧云

中文短剧剧本制作平台

如何在外部项目中动态定制已编译 Aspect 的切入点表达式

梦明姑娘_7068

梦明姑娘_7068

发布时间:2026-05-06 18:15:03

|

997人浏览过

|

来源于php中文网

原创

如何在外部项目中动态定制已编译 Aspect 的切入点表达式

本文介绍一种基于抽象 aspect 的设计模式,使已打包发布的日志切面(jar)支持被下游项目灵活定制包级切入点,无需修改原始字节码或重新编译切面模块。

本文介绍一种基于抽象 aspect 的设计模式,使已打包发布的日志切面(jar)支持被下游项目灵活定制包级切入点,无需修改原始字节码或重新编译切面模块。

在使用 AspectJ 进行横切关注点(如统一日志、监控)开发时,一个常见需求是:将核心切面逻辑封装为可复用的 Maven 依赖(如 aspectj-tool.jar),供多个业务项目直接引入;同时允许各业务方按需指定「哪些包下的方法需要被织入」——即动态变更 @Pointcut 表达式。然而,Java 规范要求注解属性必须是编译期常量,因此无法通过配置参数、系统属性或 Spring Bean 属性等方式,在运行时或编译时动态注入切入点字符串。这不是 AspectJ 的限制,而是 JVM 层面的语言约束。

解决方案是采用 面向切面的继承建模(Aspect Inheritance):将核心切面定义为抽象类,并将需定制的切入点声明为抽象方法。这样,原始切面 JAR 中仅提供通用增强逻辑(如参数记录、异常捕获、耗时统计),而具体的织入范围则交由下游项目通过子类实现。

✅ 正确实践:抽象切面 + 具体子类

首先,在基础切面模块中定义抽象 @Aspect 类:

package com.stellariver.milky.aspectj.tool.log;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
public abstract class AutoLogAspect {

    private static final Logger log = LoggerFactory.getLogger(AutoLogAspect.class);

    // 【1】注解驱动的切入点(固定逻辑)
    @Pointcut("@annotation(com.stellariver.milky.aspectj.tool.log.Log)")
    public abstract void annotationPointcut();

    // 【2】包路径驱动的切入点(由子类实现)
    @Pointcut("")
    public abstract void packagePointcut();

    // 【3】组合两个切入点,统一处理
    @Pointcut("annotationPointcut() || packagePointcut()")
    public void combinedPointcut() {}

    @Around("combinedPointcut()")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        String signature = pjp.getSignature().toShortString();
        try {
            Object result = pjp.proceed();
            long cost = System.currentTimeMillis() - start;
            log.info("[success:true] [cost:{}ms] [result:{}]", cost, result);
            return result;
        } catch (Throwable t) {
            long cost = System.currentTimeMillis() - start;
            log.error("[success:false] [cost:{}ms] [exception:{}]", cost, t.getClass().getSimpleName(), t);
            throw t;
        }
    }
}

⚠️ 注意:@Pointcut("") 是合法的占位写法,其实际表达式将在子类中被重写覆盖;AspectJ 编译器会识别该方法签名并绑定子类的具体实现。

然后,在业务项目中创建具体子类,覆盖 packagePointcut() 方法以声明目标包范围:

package com.example.log.demo;

import com.stellariver.milky.aspectj.tool.log.AutoLogAspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyLogAspect extends AutoLogAspect {

    // ✅ 动态指定:所有 com.example.log.demo 包及其子包下的任意方法
    @Pointcut("within(com.example.log.demo..*) && execution(* *(..))")
    @Override
    public void packagePointcut() {}
}

此时,业务方只需:

  • 引入 aspectj-tool 依赖;
  • 编写一个继承自 AutoLogAspect 的具体切面类;
  • 在 pom.xml 中确保 aspectj-maven-plugin 启用(CTW 模式);

即可完成无侵入式织入 —— 无需修改原始 JAR,也不需要复制粘贴整段切面代码。

? 补充说明:LTW 场景下的替代方案

若业务项目采用加载时织入(Load-Time Weaving),还可完全跳过源码继承,直接在 src/main/resources/META-INF/aop.xml 中声明:

<!DOCTYPE aspectj PUBLIC
    "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <aspects>
        <aspect name="com.stellariver.milky.aspectj.tool.log.AutoLogAspect"/>
        <!-- 子类化切面,但此处不写 Java 类,而是用 XML 显式绑定 pointcut -->
        <concrete-aspect name="com.example.log.demo.MyLogAspect"
                          extends="com.stellariver.milky.aspectj.tool.log.AutoLogAspect">
            <pointcut name="packagePointcut"
                      expression="within(com.example.log.demo..*) && execution(* *(..))"/>
        </concrete-aspect>
    </aspects>
</aspectj>

此方式甚至无需编写 Java 子类,适合对编译流程控制较弱的环境(如遗留系统集成)。

✅ 总结

方式 是否需编译子类 是否需修改原始 JAR 灵活性 推荐场景
抽象 Aspect 继承(CTW) ✅ 是 ❌ 否 高 主流 Maven 多模块项目
aop.xml concrete-aspect(LTW) ❌ 否 ❌ 否 中高 容器托管、Spring Boot 应用、灰度发布

最终,这种“契约式抽象 + 实现解耦”的设计,既保障了切面能力的标准化分发,又赋予了业务侧充分的织入策略自主权,是构建企业级 AOP 基础设施的最佳实践之一。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

3849

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2508

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

1460

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1378

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

1456

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2458

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

4100

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

19715

2023.09.22

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn