AspectJ与Kotlin中Spring Service注入失败问题求助
解决AspectJ + Kotlin中Spring Service注入失败的问题
我之前也踩过类似的坑,结合你的场景来看,核心问题是Load-Time Weaving(LTW)的代理创建时机和Spring依赖注入的顺序不匹配,再加上Kotlin的空安全特性把这个问题放大了。下面给你几个实用的解决方案,按推荐程度排序:
1. 优先使用构造函数注入(最推荐)
这是Spring官方推荐的依赖注入方式,不仅能保证依赖非空,还能从根源上避开LTW的时机冲突——因为构造函数注入是在实例创建阶段就完成依赖注入,AspectJ代理创建时会调用原类的构造函数,此时依赖已经初始化完成了。
改写你的Aspect类:
@Component class MyAspect(private val myService: MyService) { @Before("execution(* com.example.demo.service.*.*(..))") fun beforeAdvice() { myService.doSomething() } }
这样既不用lateinit也不用处理空值,Kotlin的类型安全还能帮你保证myService一定非空,调用时完全不用担心NPE或者未初始化的问题。
2. 用@Lazy配合lateinit var
如果因为某些原因没法用构造函数注入,可以给注入的Service字段加上@Lazy注解。它会让Spring生成一个代理对象,直到你第一次调用Service的方法时,才会触发真实Bean的初始化和注入,完美避开LTW代理创建时依赖未就绪的问题。
示例代码:
@Component class MyAspect { @Autowired @Lazy private lateinit var myService: MyService @Before("execution(* com.example.demo.service.*.*(..))") fun beforeAdvice() { myService.doSomething() } }
为什么原来的方式会失败?
- 用
lateinit var时:LTW会在Spring完成依赖注入之前就创建Aspect的代理实例,此时字段还没被Spring注入值,调用时自然会抛出“字段未初始化”的异常。 - 设为
null时:如果你用了可空类型var myService: MyService? = null,调用方法前没做非空判断就会触发NPE;如果强行给非空类型赋值null,这本身就不符合Kotlin的空安全规则,编译阶段就会报错。
内容的提问来源于stack exchange,提问作者user3285241
相关产品推荐
相关产品推荐

