如何让Spring AOP切面生效于Jersey管理的JaxRS服务
问题解决方法
你可以根据项目实际情况二选一,两种方案都能实现切面在JAX-RS资源上正常触发:
方案一:配置Jersey将资源实例托管给Spring容器(推荐,改动最小适配现有Spring AOP逻辑)
Spring AOP不生效的核心原因是Jersey自己走了内部的实例化逻辑创建资源对象,没走Spring容器的Bean生命周期,只要让Jersey直接从Spring容器取已经完成AOP代理的资源实例即可,操作步骤如下:
- 确认项目引入
spring-boot-starter-jersey依赖,该依赖已经内置了Jersey和Spring的官方集成模块,不需要额外引入第三方适配包。 - 给所有标注了
@Path的JAX-RS资源类加上Spring的Bean注解,必须配合@RequestScope注解使用:Jersey默认资源实例是请求级生命周期,直接用Spring默认的单例模式会出现请求上下文数据串扰的并发问题,加@RequestScope可以完全对齐原有Jersey的实例行为。 - 在你自定义的、继承自
ResourceConfig的Jersey配置类中,开启Spring组件扫描配置:
配置完成后Jersey不会自行实例化资源类,会直接从Spring容器中拉取已经完成AOP代理的对象处理请求。@Configuration public class JerseyConfig extends ResourceConfig { public JerseyConfig() { // 开启Jersey对Spring容器中Bean的识别 property(SpringProperties.SPRING_COMPONENT_SCAN, true); // 配置JAX-RS资源所在的包路径 packages("com.xxx.xxx.resource"); } } - 验证方式:启动服务后调用任意资源接口,检查切面逻辑是否正常执行;也可以在资源类构造方法打断点,看实例化时的对象类名是否包含Spring代理的标记(CGLIB动态代理会带
$$EnhancerBySpringCGLIB$$后缀)。
方案二:切换回AspectJ加载期织入,绕开Spring AOP的Bean限制
如果不想调整现有Jersey的实例化配置,可以直接沿用你在WebSphere环境下使用的AspectJ运行时织入逻辑,这种方式不关心对象是谁创建的,只要类被JVM加载就会织入切面逻辑:
- 在Spring Boot启动类上添加
@EnableLoadTimeWeaving注解开启加载期织入支持。 - 将AspectJ织入包
aspectjweaver打入Docker镜像,启动应用时在JVM参数中添加javaagent配置:java -javaagent:/opt/app/aspectjweaver-1.9.20.jar -jar your-app.jar - 在项目
resources/META-INF路径下创建aop.xml配置文件,指定要生效的切面和需要织入的目标类范围,避免全量扫描拖慢应用启动速度。
注意:如果选择方案一,不要在Jersey配置中直接通过
register(YourResource.class)的方式注册资源类,这种方式会触发Jersey自行实例化对象,覆盖Spring的代理逻辑。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

