代码之家  ›  专栏  ›  技术社区  ›  Asif Mushtaq

春季Kotlin setter依赖注入

  •  2
  • Asif Mushtaq  · 技术社区  · 7 年前

    我正在学习 spring data 因为我也在学习 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>
    

    然后我在科特林试过。

    @Component
    class StudentDao {
    
        @Autowired
        lateinit var dataSource: DataSource
    
        var jt = JdbcTemplate(dataSource)
    
    }
    

    然后我得到了例外。

    原因:Kotlin.UnnitializedPropertyAccessException:LateInit 属性数据源尚未初始化

    我知道这个例外,因为我正在使用 dataSource 之前 autowired 发生。所以我也试过这个。

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

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

    所以我如何初始化 JdbcTemplate 数据源 参数?

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

    2 回复  |  直到 7 年前
        1
  •  0
  •   zapl    7 年前

    与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中的另一个选项是在确保在实例化时不访问Lazy属性时使用该属性。

    val jt: JdbcTemplate by lazy { JdbcTemplate(dataSource) }
    
        2
  •  0
  •   noiaverbale    7 年前

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

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

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

    另外,如果你需要的话 dataSource 仅用于初始化的变量 jt ,可以删除 val 来自构造函数的键。