Springboot AOP 与 java && kotlin 和 Gradle - 它不起作用

问题描述 投票:0回答:1

我是一名学生,正在做一个Java + Spring Boot项目,我把Controller部分改成了Kotlin!然而,当我测试它时,所有使用@Before Aop的API在从控制器调用服务时都会生成NPE,并且服务为空! Java Controller -> AOP 工作正常,但不知道为什么。

下面是代码

控制器

@RestController
@RequestMapping("/")
open class SampleController (
    private val sampleService: SampleService){

   @GetMapping
   fun test(){
   println("TEST In ")
  }
}

AOP

@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class PreProcess{
   @Before("@within(org.springframework.web.bind.annotation.RestController)")
public void doProcess(JoinPoint joinPoint) {
   log.info("####### ASPECT IN ")
}
}

总结一下 如果你烧写Java Controller API,方面和控制器日志都会被记录并正常运行。

如果烧录 Kotlin 控制器 API,会出现 NPE(无法调用 SampleService,因为 this.SampleService 为 null ~~~~)

解决办法是什么?,,,,,,,

我通过创建一个新项目进行了测试,还删除了似乎相关的gradle。

java spring-boot kotlin spring-aop spring-kotlin
1个回答
0
投票

您的问题似乎是由组件的初始化顺序问题引起的。当

@Before
方面尝试访问
sampleService
时,其初始化可能尚未完成,从而导致
NullPointerException
(NPE),因为它使用
sampleService

为了确保

sampleService
在被访问之前初始化,您可以将
sampleService
转换为
lateinit var
并使用字段注入自动装配它。您的 Kotlin 控制器可能如下所示:

@RestController
@RequestMapping("/")
open class SampleController : SampleService{

    @Autowired 
    lateinit var sampleService: SampleService

   @GetMapping
   fun test() {
        println("TEST In ")
    }
}

请记住,由于初始化语义可能不明确,使用

lateinit var
并不总是最佳选择。

另一个潜在问题可能与 Lombok 的

@RequiredArgsConstructor
注释在 Kotlin 中使用时不兼容有关,因为 Kotlin 不会生成此注释所需的零参数构造函数。

更好的选择是您构建自己的构造函数以在方面中进行依赖项注入。

@Aspect
@Component
@Slf4j
class PreProcess(
    private val sampleService: SampleService) {
    @Before("@within(org.springframework.web.bind.annotation.RestController)")
    fun doProcess(joinPoint: JoinPoint) {
        log.info("####### ASPECT IN ")
    }
}

不过,一般来说,将服务组件与方面混合起来并不是一个好主意,因为它们是针对不同的关注点的。

© www.soinside.com 2019 - 2024. All rights reserved.