Spring Boot @Autowired with Kotlin in @Service is always null

后端 未结 3 1484
闹比i
闹比i 2021-02-19 00:21

Currently I try to rewrite my Java Spring Boot Application with Kotlin. I encountered a problem that in all of my classes which are annotated with @Service the depe

相关标签:
3条回答
  • 2021-02-19 01:01

    I faced the same problem working with Kotlin but the null instance was a JpaRepository. When I added the @Transactional annotation to a method inside a service, I got a message saying Methods annotated with '@Transactional' must be overridable so I went ahead and marked both, the class and the method as open. Easy, right?! Well, not quite.

    Although this compiles, I got the required repository as null at execution time. I was able to solve the problem in two ways:

    1. Mark the class and ALL of its methods as open:
    open class FooService(private val barRepository: BarRepository) {
        open fun aMethod(): Bar {
            ...
        }
    
        @Transactional
        open fun aTransactionalMethod(): Bar {
            ...
        }
    }
    

    This works but having all the methods in a class marked with open might look a bit odd, so I tried something else.

    1. Declare an interface:
    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 {
            ...
        }
    }
    

    This way you can still use the annotation since all the methods will be overridable and you won't need to use open everywhere.

    Hope this helps =)

    0 讨论(0)
  • 2021-02-19 01:07

    Which Spring Boot version do you use? Since 1.4 Spring Boot is based on Spring Framework 4.3 and since then you should be able to use constructor injection without any @Autowired annotation at all. Have you tried that?

    It would look like this and works for me:

    @Service
    class UserServiceController(val dsl: DSLContext, val teamService: TeamService) {
    
      // your class members
    
    }
    
    0 讨论(0)
  • 2021-02-19 01:08

    I just bumped into exactly same issue - injection worked well, but after adding @Transactional annotation all the autowired fields are null.

    My code:

    @Service
    @Transactional  
    open class MyDAO(val jdbcTemplate: JdbcTemplate) {
    
       fun update(sql: String): Int {
           return jdbcTemplate.update(sql)
       }
    
    } 
    

    The problem here is that the methods are final by default in Kotlin, so Spring is unable to create proxy for the class:

     o.s.aop.framework.CglibAopProxy: Unable to proxy method [public final int org.mycompany.MyDAO.update(...
    

    "Opening" the method fixes the issue:

    Fixed code:

    @Service
    @Transactional  
    open class MyDAO(val jdbcTemplate: JdbcTemplate) {
    
       open fun update(sql: String): Int {
           return jdbcTemplate.update(sql)
       }
    
    } 
    
    0 讨论(0)
提交回复
热议问题