You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Kotlin中BeanCreationException问题求助

Kotlin Spring Boot @Transactional 导致CGLIB代理失败问题解决

问题代码

SomeConfig.kt

@Configuration
class SomeConfig {

    @Bean
    fun someServiceBean() = object : MyService {
        @Transactional
        override fun doWork(): String {
            return "Some work have been done"
        }
    }

    @Bean
    fun cliRunner(myService: MyService): CommandLineRunner = CommandLineRunner {
        myService.doWork()

        println(myService.doWork())
    }
}

MyService.kt

interface MyService {
    fun doWork(): String
}

启动错误日志

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-11-09T10:53:45.047+03:00 ERROR 22666 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someServiceBean' defined in class path resource [ru/mindtable/config/SomeConfig.class]: Could not generate CGLIB subclass of class ru.mindtable.config.SomeConfig$someServiceBean$1: Common causes of this problem include using a final class or a non-visible class
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:605) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:950) ~[spring-context-6.0.13.jar:6.0.13]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:616) ~[spring-context-6.0.13.jar:6.0.13]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.5.jar:3.1.5]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:738) ~[spring-boot-3.1.5.jar:3.1.5]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:440) ~[spring-boot-3.1.5.jar:3.1.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-3.1.5.jar:3.1.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-3.1.5.jar:3.1.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-3.1.5.jar:3.1.5]
    at ru.mindtable.config.TaskTrackerApplicationKt.main(TaskTrackerApplication.kt:13) ~[main/:na]
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class ru.mindtable.config.SomeConfig$someServiceBean$1: Common causes of this problem include using a final class or a non-visible class
    at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:222) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:155) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildProxy(AbstractAutoProxyCreator.java:517) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:464) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:369) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:318) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:434) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1773) ~[spring-beans-6.0.13.jar:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.13.jar:6.0.13]
    ... 15 common frames omitted
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class ru.mindtable.config.SomeConfig$someServiceBean$1
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:653) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:26) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:57) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:366) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52) ~[spring-core-6.0.13.jar:6.0.13]
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:57) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:130) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:317) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:562) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:407) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:62) ~[spring-aop-6.0.13.jar:6.0.13]
    at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:213) ~[spring-aop-6.0.13.jar:6.0.13]
    ... 24 common frames omitted

问题原因

Kotlin中匿名对象默认是final类,而Spring的@Transactional注解默认使用CGLIB代理实现事务增强,CGLIB需要生成目标类的子类来织入逻辑,final类无法被继承,因此报错。

解决方案

方案1:将匿名对象改为open的具名类

把匿名实现的MyService替换为显式的open类,允许Spring生成子类代理:

@Configuration
class SomeConfig {

    open class MyServiceImpl : MyService {
        @Transactional
        override fun doWork(): String {
            return "Some work have been done"
        }
    }

    @Bean
    fun someServiceBean() = MyServiceImpl()

    @Bean
    fun cliRunner(myService: MyService): CommandLineRunner = CommandLineRunner {
        myService.doWork()
        println(myService.doWork())
    }
}

方案2:使用JDK动态代理替代CGLIB

通过配置让Spring使用基于接口的JDK动态代理,不需要子类化目标类:

  1. 在application.properties中添加配置:
spring.aop.proxy-target-class=false
  1. 可将@Transactional注解移到接口方法上(可选,增强可读性):
interface MyService {
    @Transactional
    fun doWork(): String
}

方案3:使用@Transactional的proxyTargetClass属性(局部配置)

如果不想全局修改代理方式,可以在@Transactional注解中指定使用JDK代理:

@Transactional(proxyTargetClass = false)
override fun doWork(): String {
    return "Some work have been done"
}

内容的提问来源于stack exchange,提问作者Артем Жуйков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:19:51