由于生成了@Metadata注释,Spring框架未能在kotlin文件中检测到bean



经过一周的搜索,我自己发现了这个问题,我使用Kotlin创建了JPA实体类,这本应该是允许的(我在互联网上看到了多个例子(,但在我的情况下失败了。

为了显示一个示例,我创建了两个文件,它们都描述了具有自动生成的Id和String的同一实体bean,一个文件是纯Java,一个是Kotlin

Java版本:

@Entity
public class Example {
@Id
@GeneratedValue
Long Id;
String name;
public Example() {} //for jpa
public Example(Long Id, String name) {
this.Id = Id;
this.name = name;
}
}

它工作正常,应用程序启动没有问题。

现在有一个Kotlin版本:

@Entity
open class Example(@Id @GeneratedValue var Id : Long,
var name : String){
}

尝试运行应用程序现在失败了,出现了一个通用的java.lang.NoClassDefFoundError,它来自于试图使用Example类的其他类(当然,我不会同时保留两个版本(。我现在也明白了,它本身不会工作,因为不需要arg构造函数,但它甚至还没有检测到类!

我分析了Kotlin编译器生成的内容,并注意到自动生成的@Metadata注释是罪魁祸首。我甚至尝试在java版本的类中添加一个空的,看看会发生什么,它确实给出了相同的NoClassDefFoundError。此外,我应该注意到Kotlin集成是有效的,因为它不是唯一的文件(我有CrudRepository接口的Kotlin文件,它有效吗?…(

所以我的问题是,我该如何解决这个问题?是否可能禁用元数据注释,或者我做错了什么?

注意:当我把所有的东西都放在一个文件中时,我以前可以把kotlin类和spring一起使用,这似乎是把代码拆分成更小的文件,扰乱了的所有内容

这个Entity类是这样通过CrudRepository使用的(注意它是Kotlin,将它移植到Java没有什么区别(

@Repository
interface FileRepo : CrudRepository<Example, Long> {}

另一个管理器类可以做到这一点:


@Controller
public class FileUploadController {
private final FileRepo fileRepo;
@Autowired
public FileUploadController(FileRepo fileRepo) {
this.fileRepo = fileRepo;
}
...
Example tosave = new Example(Idhere, nameHere);
this.fileRepo.save(tosave);

这是我的等级项目:

plugins {
id 'org.springframework.boot' version '2.5.2'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.5.20'
}
group = 'pl.szpring'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
runtimeOnly "com.h2database:h2:1.4.200"
}
test {
useJUnitPlatform()
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}

完整错误日志(引用一个使用CrudRepository:的类

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fileUploadController' defined in file [(path here)javamainplszpringwysylanieFileUploadController.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fileRepo' defined in pl.szpring.wysylanie.storage.FileRepo defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: kotlin/reflect/full/KClasses
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.8.jar:5.3.8]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.8.jar:5.3.8]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.2.jar:2.5.2]
at pl.szpring.wysylanie.MainKt.main(main.kt:39) ~[main/:na]```

原来错误日志一直在暗示出了什么问题,我错过了kotlin反射依赖性(此处为gradle(:

dependencies {
runtimeOnly 'org.jetbrains.kotlin:kotlin-reflect:1.2.41'
...
}

最新更新