如何在其他项目中修改已编译Aspect的PointCut表达式?
解决方案:参数化AspectJ切面切入点
针对已编译切面Jar无法动态修改customPointCut包路径的问题,提供以下几种实用方案:
方案一:基于系统属性的动态切入点(零代码配置)
步骤1:修改原切面的切入点表达式
调整LogAspect,将固定包路径替换为带默认值的系统属性占位符:
@Aspect public class LogAspect { static private final Logger log = Logger.getLogger(LogAspect.class); @Pointcut("execution(@com.stellariver.milky.aspectj.tool.log.Log * *(..))") private void annoPointCut() {} // 使用系统属性占位符,默认值设为无效包避免误切 @Pointcut("execution(* ${custom.log.package:invalid.package}..*.*(..))") private void customPointCut() {} @Around("annoPointCut() || customPointCut()") public Object valid(ProceedingJoinPoint pjp) throws Throwable { Object result = null; try { result = pjp.proceed(); } catch (Throwable throwable) { throw throwable; } finally { // 原有日志逻辑 } return result; } }
步骤2:同事项目中配置织入参数
同事在自己的项目中,通过aspectj-maven-plugin传递系统属性指定目标包:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <source>1.8</source> <target>1.8</target> <aspectLibraries> <aspectLibrary> <groupId>你的切面groupId</groupId> <artifactId>你的切面artifactId</artifactId> </aspectLibrary> </aspectLibraries> <!-- 传递自定义包路径的系统属性 --> <compilerArgs> <arg>-Dcustom.log.package=com.project.target.package</arg> </compilerArgs> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin>
优点:同事无需编写任何代码,仅需配置Maven参数即可;缺点:依赖AspectJ 1.8+的系统属性解析支持,且同一项目只能指定单一包路径。
方案二:公共切点扩展(高灵活性)
步骤1:修改原切面的切点可见性
将customPointCut改为公共空切点,供依赖项目扩展:
@Aspect public class LogAspect { static private final Logger log = Logger.getLogger(LogAspect.class); @Pointcut("execution(@com.stellariver.milky.aspectj.tool.log.Log * *(..))") private void annoPointCut() {} // 定义公共空切点,允许外部扩展 @Pointcut("") public void customPointCut() {} @Around("annoPointCut() || customPointCut()") public Object valid(ProceedingJoinPoint pjp) throws Throwable { // 原有逻辑不变 } }
步骤2:同事项目中扩展切点
同事只需在自己的项目中创建一个简单的切面类,自定义目标包的切点:
@Aspect public class CustomLogPointcut { // 与原切面同名的公共切点,AspectJ会自动合并逻辑 @Pointcut("execution(* com.project.target.package..*.*(..))") public void customPointCut() {} }
优点:支持任意复杂的切点表达式(不仅限于包),灵活性极高;缺点:需要编写一行极简的切点代码。
方案三:Maven资源过滤生成自定义切面(完全零代码)
如果希望同事完全不编写代码,可将切面做成模板,通过Maven资源过滤动态生成:
- 将你的
LogAspect.java改为模板文件LogAspect.java.template,替换包路径为占位符:
@Aspect public class LogAspect { static private final Logger log = Logger.getLogger(LogAspect.class); @Pointcut("execution(@com.stellariver.milky.aspectj.tool.log.Log * *(..))") private void annoPointCut() {} @Pointcut("execution(* ${custom.log.package}..*.*(..))") private void customPointCut() {} @Around("annoPointCut() || customPointCut()") public Object valid(ProceedingJoinPoint pjp) throws Throwable { // 原有逻辑 } }
- 同事的项目中引入你的切面源码依赖,开启Maven资源过滤替换占位符后编译。
优点:完全无需编写代码;缺点:需要处理源码依赖和资源过滤配置,复杂度较高,不推荐作为首选方案。
内容的提问来源于stack exchange,提问作者Chuang Hou
相关产品推荐
相关产品推荐

