尝试在Kotlin和Spring引导下使用JPA时出现BeanDefinitionParsingException

当我尝试使用springboot + JPA + kotlin + maven时,我得到这个异常

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: @Bean method 'init' must not be private or final; change the method's modifiers to continue Offending resource: com.wirecard.kotlin.jpa.Application at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70) at org.springframework.context.annotation.BeanMethod.validate(BeanMethod.java:50) at org.springframework.context.annotation.ConfigurationClass.validate(ConfigurationClass.java:219) at org.springframework.context.annotation.ConfigurationClassParser.validate(ConfigurationClassParser.java:528) at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:307) at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:239) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) at org.springframework.boot.SpringApplication.run(SpringApplication.java:957) at org.springframework.boot.SpringApplication.run(SpringApplication.java:946) at com.wirecard.kotlin.jpa.ApplicationKt.main(Application.kt:50) 

我遵循这个链接的例子,但它是使用Gradle构建的

Kotlin和JPA的Springboot应用程序

代码由3个类组成

客户类

 import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id @Entity class Customer( val firstName: String, val lastName: String, @Id @GeneratedValue(strategy = GenerationType.AUTO) val id: Long = -1) { override fun toString(): String { return "Customer(id=$id, firstName='$firstName', lastName='$lastName')" } } 

类CustomerController

 import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RestController @RestController class CustomerController(val repository:CustomerRepository) { @GetMapping("/") fun findAll() = repository.findAll() @GetMapping("/{lastName}") fun findByLastName(@PathVariable lastName:String) = repository.findByLastName(lastName) } 

接口CustomerRepository

 import org.springframework.data.repository.CrudRepository interface CustomerRepository : CrudRepository<Customer, Long> { fun findByLastName(lastName: String): Iterable<Customer> } 

从日志看来,它实际上是第4类, Application ,你遇到了问题。 它说这个类中的init方法不应该是private或者final ,这里的问题就是后者–Kotlin中的函数和类是默认的final的。

您可以通过使用open关键字标记方法使该方法不是最终的。

 @Bean open fun init(repository: CustomerRepository) = CommandLineRunner { ... } 

您还必须使用open关键字标记您的Application类。

 @SpringBootApplication open class Application { ... } 

这些open关键字不在这个例子中的原因是因为它使用了kotlin-spring插件( 参见构建脚本 ),它打开了Spring要求的非类型的类和函数。

如果你不想手动open你的类,你应该也可以使用Maven的kotlin-spring插件。 这样做的说明正好在Gradle指令之上,在关于all-open插件的章节结尾。 你只需要包含那里的代码,并用<plugin>spring</plugin>替换<plugin>all-open</plugin> <plugin>spring</plugin> ,就像这里的注释所描述的那样。