简体   繁体   English

春季Kotlin setter依赖注入

[英]Kotlin setter dependency Injection in Spring

I'm learning about spring data and because I'm also learning about kotlin so I decided to work with kotlin during spring learning. 我正在学习spring data ,因为我也在学习kotlin所以我决定在春季学习期间与kotlin一起工作。 So I want to ask how we can Implement setter dependency injection in kotlin? 所以我想问一下如何在Kotlin中实现setter依赖注入? as in Java we can that as below. 就像在Java中一样,我们可以做到如下。

@Component
public class StudentDaoImp {

    public DataSource dataSource;

    public JdbcTemplate jdbcTemplate;

    public DataSource getDataSource() {
        return dataSource;
    }

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

And here is my spring.xml file. 这是我的spring.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">


    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:~/test" />
    </bean>

    <context:component-scan base-package="com.package.*" />
</beans>

Then I tried it in kotlin. 然后我在科特林尝试过。

@Component
class StudentDao {

    @Autowired
    lateinit var dataSource: DataSource

    var jt = JdbcTemplate(dataSource)

}

Then I'm getting the exception. 然后我得到了例外。

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property dataSource has not been initialized 原因:kotlin.UninitializedPropertyAccessException:lateinit属性dataSource尚未初始化

I know about this exception because I'm using dataSource before autowired happen. 我知道此异常,因为在autowired发生之前我正在使用dataSource So I have also tried this. 所以我也尝试过。

@Autowired
fun setDataSource(dataSource: DataSource) {
    this.jt = JdbcTemplate(dataSource)
}

This is also an error, because JVM already have that signature behind the scene. 这也是一个错误,因为JVM已经在后台隐藏了该签名。

So how I can Initialize JdbcTemplate with the dataSource parameter? 那么,如何使用dataSource参数初始化JdbcTemplate

Note: I only want Code side example/solution. 注意:我只想要代码方面的示例/解决方案。 I know about the XML solution. 我了解XML解决方案。

like in Java you can't use properties that are injected after instantiation at instantiation time. 像在Java中一样,您不能使用实例化实例化注入的属性。 In Java you'd get a NullPointerException when you would do the equivalent, eg 在Java中,当您进行等效操作时,会得到NullPointerException ,例如

@Autowired
private Datasource datasource;
private JdbcTemplate jt = new JdbcTemplace(dataSource);

But you can let Spring call a method of your choice after it has injected everything: 但是您可以在注入所有内容后让Spring调用您选择的方法:

lateinit var jt: JdbcTemplate
@PostConstruct
fun initAfterAutowireIsDone() {
    jt = JdbcTemplate(dataSource)
}

There is also the InitializingBean interface that can be used instead of the annotation. 还可以使用InitializingBean接口代替注释。 The same works in Java. 在Java中也是如此。

The other option you have in Kotlin is to use a lazy property when you ensure you don't access it at instantiation time. 您在Kotlin中拥有的另一个选择是,当您确保在实例化时不访问它时,请使用惰性属性。

val jt: JdbcTemplate by lazy { JdbcTemplate(dataSource) }

While I consider zapl answer correct, I would also suggest you to consider constructor arguments injection: 当我认为zapl答案正确时,我也建议您考虑构造函数参数注入:

@Component
class StudentDao @Autowired constructor(
    private val dataSource: DataSource
) {

    private val jt = JdbcTemplate(dataSource)

}

In this way you can obtain non modifiable variables without warning about late initialization. 这样,您可以获取不可修改的变量,而无需发出有关后期初始化的警告。

Also, if you need dataSource variable only to initialize jt , you can remove val key from constructor. 另外,如果只需要dataSource变量来初始化jt ,则可以从构造函数中删除val键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM