关于aspectj-maven-plugin weave dependency特性类加载随机性的问询
你的猜测是成立的:当类路径中存在全限定名完全一致的两个类时,JVM类加载器会按照类路径的先后顺序加载第一个找到的类。Jar包部署时的类路径顺序往往和IDEA运行时不同,这就导致部署后可能加载到未被织入切面的原始业务类,最终出现切面不生效的问题。
针对这个问题,有几种可靠的解决机制:
调整AspectJ插件输出,避免生成重复类
在ajc模块的aspectj-maven-plugin配置中,修改输出目录,不要把织入后的业务类放到模块主classpath下。可以将织入后的类输出到单独的临时目录,再通过maven-dependency-plugin将这些类替换掉业务模块Jar中的原始类。这样类路径里只会存在一份织入后的类,彻底避免冲突。优化依赖与打包策略,保证织入类唯一
要么调整starter模块的依赖顺序,让ajc模块的依赖排在业务模块之前,让类加载器优先加载织入后的类;要么使用maven-shade-plugin将ajc模块中织入后的类合并到业务模块的Jar里,直接替换原始类,最终只保留一份包含切面的业务Jar。前者依赖类路径顺序,稳定性稍差,后者更推荐。将织入逻辑移到业务模块内部
如果你能调整Lombok和AspectJ插件的执行顺序,让Lombok先处理业务类生成字节码,再由AspectJ织入,可以把aspectj-maven-plugin配置在业务模块中,直接对自身类进行织入。具体可以在业务模块的pom.xml里,把Lombok插件的执行阶段设为generate-sources,AspectJ插件设为process-classes,确保执行顺序正确。这样业务模块的Jar里就是已经织入切面的类,不会有重复类问题。改用AspectJ加载时编织(LTW)
放弃编译时编织,改用加载时编织。项目里配置aop.xml指定要织入的切面和目标类,然后在JVM启动参数中添加-javaagent:aspectjweaver.jar,让JVM在加载类时动态织入切面。这种方式不会生成重复类文件,从根源上解决类冲突,不过需要额外配置JVM启动参数。
内容的提问来源于stack exchange,提问作者Chuang Hou

