【问题标题】:Kotlin setter dependency Injection in SpringSpring中的Kotlin setter依赖注入
【发布时间】:2018-09-25 15:32:27
【问题描述】:

我正在学习 spring data,因为我也在学习 kotlin,所以我决定在春季学习期间使用 kotlin。所以我想问一下我们如何在kotlin中实现setter依赖注入?在 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;
    }
}

这是我的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>

然后我在kotlin中试了一下。

@Component
class StudentDao {

    @Autowired
    lateinit var dataSource: DataSource

    var jt = JdbcTemplate(dataSource)

}

然后我得到了异常。

引起:kotlin.UninitializedPropertyAccessException:lateinit 属性 dataSource 尚未初始化

我知道这个异常,因为我在 autowired 发生之前使用了 dataSource。所以我也试过这个。

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

这也是一个错误,因为 JVM 在幕后已经有了那个签名。

那么如何使用dataSource参数初始化JdbcTemplate

注意:我只想要代码端示例/解决方案。我知道 XML 解决方案。

【问题讨论】:

    标签: java spring kotlin


    【解决方案1】:

    就像在Java 中一样,您不能使用在 实例化 实例化时间注入的属性。在 Java 中,你会得到一个 NullPointerException,当你做同样的事情时,例如

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

    但是您可以让 Spring 在注入所有内容后调用您选择的方法:

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

    还有InitializingBean接口可以代替注解使用。在 Java 中也是如此。

    您在 Kotlin 中拥有的另一个选项是在确保在实例化时不访问它时使用惰性属性。

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

    【讨论】:

      【解决方案2】:

      虽然我认为 zapl 答案正确,但我也建议您考虑构造函数参数注入:

      @Component
      class StudentDao @Autowired constructor(
          private val dataSource: DataSource
      ) {
      
          private val jt = JdbcTemplate(dataSource)
      
      }
      

      通过这种方式,您可以获得不可修改的变量,而不会发出延迟初始化的警告。

      另外,如果您只需要dataSource 变量来初始化jt,您可以从构造函数中删除val 键。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-25
        • 1970-01-01
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        • 2015-10-04
        • 1970-01-01
        相关资源
        最近更新 更多