在@Service中与@Kutlin一起使用的Spring Boot始终为null

Deu*_*tro 15 java spring spring-mvc kotlin spring-boot

目前我尝试使用Kotlin重写我的Java Spring Boot应用程序.我遇到了一个问题,在我的所有使用@Service依赖注入注释的类中都没有正常工作(所有实例都是null).这是一个例子:

@Service
@Transactional
open class UserServiceController @Autowired constructor(val dsl: DSLContext, val teamService: TeamService) {
  //dsl and teamService are null in all methods
}
Run Code Online (Sandbox Code Playgroud)

在Java中做同样的工作没有任何问题:

@Service
@Transactional
public class UserServiceController
{
    private DSLContext dsl;
    private TeamService teamService;

    @Autowired
    public UserServiceController(DSLContext dsl,
                             TeamService teamService)
    {
        this.dsl = dsl;
        this.teamService = teamService;
    }
Run Code Online (Sandbox Code Playgroud)

如果我用@ComponentKotlin 注释组件一切正常:

@Component
open class UserServiceController @Autowired constructor(val dsl: DSLContext, val teamService: TeamService) {
  //dsl and teamService are injected properly
}
Run Code Online (Sandbox Code Playgroud)

谷歌为Kotlin提供了许多不同的方法,@Autowired但我尝试了所有方法,但NullPointerException 我想知道Kotlin和Java之间的区别是什么以及如何解决这个问题?

mir*_*ran 13

我只是碰到了完全相同的问题 - 注入效果很好,但在添加@Transactional注释后,所有自动连接的字段都为空.

我的代码:

@Service
@Transactional  
open class MyDAO(val jdbcTemplate: JdbcTemplate) {

   fun update(sql: String): Int {
       return jdbcTemplate.update(sql)
   }

} 
Run Code Online (Sandbox Code Playgroud)

这里的问题是默认情况下Kotlin中的方法是final的,所以Spring无法为类创建代理:

 o.s.aop.framework.CglibAopProxy: Unable to proxy method [public final int org.mycompany.MyDAO.update(...
Run Code Online (Sandbox Code Playgroud)

"打开"方法修复了问题:

固定代码:

@Service
@Transactional  
open class MyDAO(val jdbcTemplate: JdbcTemplate) {

   open fun update(sql: String): Int {
       return jdbcTemplate.update(sql)
   }

} 
Run Code Online (Sandbox Code Playgroud)


小智 7

我在使用 Kotlin 时遇到了同样的问题,但 null 实例是 JpaRepository。当我将@Transactional注释添加到服务内的方法时,我收到一条消息,说Methods annotated with '@Transactional' must be overridable所以我继续将类和方法都标记为open. 很容易,对吧?嗯,不完全是。

尽管可以编译,但我在执行时将所需的存储库设置为空。我能够通过两种方式解决这个问题:

  1. 将类及其所有方法标记为open
open class FooService(private val barRepository: BarRepository) {
    open fun aMethod(): Bar {
        ...
    }

    @Transactional
    open fun aTransactionalMethod(): Bar {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这可行,但是将类中的所有方法标记为open可能看起来有点奇怪,所以我尝试了其他方法。

  1. 声明一个接口:
interface IFooService {
    fun aMethod(): Bar

    fun aTransactionalMethod(): Bar
}

open class FooService(private val barRepository: BarRepository) : IFooService {
    override fun aMethod(): Bar {
        ...
    }

    @Transactional
    override fun aTransactionalMethod(): Bar {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这样您仍然可以使用注释,因为所有方法都将是可重写的,并且您不需要open在任何地方使用。

希望这有帮助 =)


Dav*_*vid 4

您使用哪个 Spring Boot 版本?由于 1.4 Spring Boot 基于 Spring Framework 4.3,从那时起您应该能够使用构造函数注入而无需任何@Autowired注释。你尝试过吗?

它看起来像这样并且对我有用:

@Service
class UserServiceController(val dsl: DSLContext, val teamService: TeamService) {

  // your class members

}
Run Code Online (Sandbox Code Playgroud)