programing

스프링 부트 @Autowired with Kotlin in @Service는 항상 null입니다.

iphone6s 2023. 3. 23. 22:23
반응형

스프링 부트 @Autowired with Kotlin in @Service는 항상 null입니다.

현재 Kotlin에서 Java Spring Boot Application을 다시 작성하려고 합니다.나는 내 모든 수업에서 다음과 같이 주석을 다는 문제에 직면했다.@Service종속성 주입이 올바르게 작동하지 않습니다(모든 인스턴스는null)의 예를 다음에 나타냅니다.

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

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;
    }

컴포넌트에 주석을 달면@Component코틀린에서는 모든 것이 정상적으로 동작합니다.

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

구글은 Kotlin과 Kotlin을 위해 많은 다른 접근 방식을 제공했습니다.@Autowired내가 시도했지만 모두 같은 결과가 되었다.NullPointerExceptionKotlin과 Java의 차이와 수정 방법을 알고 싶습니다.

방금 똑같은 문제에 부딪혔는데 주입은 잘 되었지만 @Transactional 주석을 추가한 후에는 모든 자동 입력 필드가 null이 됩니다.

내 코드:

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

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

} 

여기서의 문제는 메서드가 기본적으로 Kotlin에서 최종적이기 때문에 Spring은 클래스의 프록시를 만들 수 없다는 것입니다.

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

이 방법을 "열기"하면 문제가 해결됩니다.

고정 코드:

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

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

} 

Kotlin에서 작업하는 경우에도 동일한 문제가 발생했지만 null 인스턴스는 JpaRepository였습니다.를 추가했을 때@Transactional서비스 내 메서드에 대한 주석, 다음과 같은 메시지를 받았습니다.Methods annotated with '@Transactional' must be overridable그래서 나는 수업과 방법 둘 다로 표시했다.open쉽죠?글쎄, 꼭 그렇진 않아.

이것은 컴파일되지만 실행 시 필요한 저장소는 null로 취득되었습니다.저는 두 가지 방법으로 문제를 해결할 수 있었습니다.

  1. 클래스 및 모든 메서드를 다음과 같이 표시합니다.open:
open class FooService(private val barRepository: BarRepository) {
    open fun aMethod(): Bar {
        ...
    }

    @Transactional
    open fun aTransactionalMethod(): Bar {
        ...
    }
}

이것은 동작하지만 클래스 내의 모든 메서드에 마크가 붙어 있습니다.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 {
        ...
    }
}

이렇게 하면 모든 메서드를 덮어쓸 수 있으므로 주석을 계속 사용할 수 있습니다.open온통.

도움이 되길 바랍니다 =)

어떤 스프링 부트 버전을 사용하고 있습니까?1.4 Spring Boot은 Spring Framework 4.3을 기반으로 하기 때문에 그 이후로 컨스트럭터 주입을 사용하지 않고 사용할 수 있습니다.@Autowired주석을 달아야 합니다.그거 먹어봤어?

다음과 같이 생겼고, 나에게도 효과가 있습니다.

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

  // your class members

}

언급URL : https://stackoverflow.com/questions/41298289/spring-boot-autowired-with-kotlin-in-service-is-always-null

반응형