¿Cómo puedo usar las propiedades lateinit en mi constructor de clase?
Tengo un componente de resorte que uso para configurar y acceder a una biblioteca de terceros así:
@Service class LibProxy { @Value("\${lib.someProperty}") private lateinit var someProperty: String final var lib: Lib init { lib = Lib(someProperty) } }Esto da un
kotlin.UninitializedPropertyAccessException: lateinit property someProperty has not been initialized¿Cómo se supone que se debe hacer esto?
Me gustaría evitar construcciones como esta:
@Service class LibProxy { @Value("\${lib.someProperty}") private lateinit var someProperty: String private var lib: Lib? = null getLib(): Lib { if (lib == null) { lib = Lib(someProperty) } return lib ?: Lib(someProperty) } }Dos posibilidades aquí:
La más fácil es reemplazar el bloque de inicio con @PostConstruct init Spring llamará a esto una vez, después de que se haya construido el objeto (y, por lo tanto, los valores de conexión automática estén todos configurados). Por ejemplo:
@PostConstruct private fun initialise() { lib = Lib(someProperty) }El otro es hacer arreglos para que la propiedad autocableada se pase en un constructor, no se establezca como una propiedad (según otras respuestas).
Un enfoque que funciona bien, especialmente si tiene varias propiedades de configuración, es tener una clase central que las almacene:
@ConfigurationProperties("lib") class ConfigProperties { var someProperty = "defaultValue" // …and other properties… } Esto establecerá someProperty desde un valor "lib.someProperty" en un archivo de configuración (o dejado como "defaultValue" si no está presente).
Luego puede autoconectar su instancia en el constructor, por ejemplo:
class SomeService @Autowired constructor( private val configProperties: ConfigProperties) { init { lib = Lib(configProperties.someProperty) } }(La centralización de las propiedades también puede hacer que sea más fácil encontrar qué propiedades están disponibles).