编程语言
首页 > 编程语言> > Spring Java Config – @DependsOn chaining

Spring Java Config – @DependsOn chaining

作者:互联网

我有一个3.2.14.RELEASE spring应用程序,并使用java配置连接和注入bean.

在我的情况下,我需要

>设置SSH隧道
>创建一个DataSource,使其使用相同的ssh
隧道会议
>创建一个Query类,使用它执行SQL查询
一个JDBCTemplate

我已经使用@DependsOn注释设置了我的ApplicationContext链接以链接三个bean

package com.b.e.kpireport;

@Configuration
@ComponentScan(basePackages = {"com.b.e.kpireport" })
public class ApplicationContext {

    @Bean(name = "sshTunnel")
    public SSHTunnel getSSHTunnel() {
        return new SSHTunnel();
    }

    @Bean(name = "dataSource" )
    @DependsOn("sshTunnel")
    public DataSource getDataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        logger.info("getDataSource():"+jdbcUrl+":"+username+"/"+password+":"+driver);
        return dataSource;
    }

    @Bean
    @DependsOn("dataSource")
    public Query getQuery() {
        return new Query();
    }  
}

Query类看起来像

class Query {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private SSHTunnel sshTunnel;

    public void runQuery() {
        sshTunnel.openSession();
        jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.execute(sql);
    }

无论我尝试过什么,我都看到dataSource在SSHTunnel之前被初始化了

Aug 26, 2015 5:20:44 PM com.b.e.kpireport.ApplicationContext getDataSource
INFO: getDataSource():jdbc:mysql://localhost:3006/centstorage:davidobrien/MnBufeuwncv3eR:com.mysql.jdbc.Driver
Aug 26, 2015 5:20:44 PM com.b.e.kpireport.SSHTunnel openSession
INFO: openSession

关于如何确保正确的bean初始化顺序的任何建议?

解决方法:

解决方案实际上可能很简单:

@Configuration
public class ApplicationContext {
    @Bean(name = "sshTunnel")
    public SSHTunnel getSSHTunnel() {
        return new SSHTunnel();
    }

    @Bean(name = "dataSource" )
    public DataSource getDataSource() {
         getSHTunnel();
         DriverManagerDataSource dataSource = new DriverManagerDataSource();
         // ...
         return dataSource;
    }

    @Bean
    public Query getQuery() {
        return new Query(getSSHTunnel(), getDataSource());
    }  
}

我们经常使用这种调用配置类方法的模式(在类中).在创建上下文时,不会直接在您的类上调用这些方法,而是在Spring动态创建的子类上调用这些方法.这确保即使您多次调用方法(例如getSSHTunnel()),也只创建一次相应的bean(即只创建一个隧道).

我也更喜欢通过构造函数而不是@Autowired传递依赖关系 – 它不那么神奇,也更容易测试.这是可选的.

我不知道为什么使用@DependsOn对你不起作用.当我在本地尝试它时,它工作(使用相同的Spring版本).无论如何,以上是一个如何完全没有它的例子.

编辑以回应评论:

But in this case you can just delete all the spring annotations since you are not doing any dependency injection. You’ve basically just got a plain old java object

事实并非如此.正如我所说,在@Configuration对象上调用方法不会直接调用您的方法,但是它的版本会被Spring returning the bean according to configuration覆盖.这允许您进行适当的依赖注入,例如在这样的测试中:

@Configuration 
public class TestDependencies {
    @Bean(name="dataSource")
    public DataSource getDataSource() {
        return new MockDataSource();
    }
}
...
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class, TestDependencies.class);
context.getBean("dataSource"); // returns MockDataSource

换句话说,调用getDataSource()之类的方法实际上等同于具有依赖性@Autowired或使用context.getBean().这种方法没有任何陷阱AFAIK(只要你不将参数传递给@Bean方法,否则事情会变得有点奇怪)并且我们已经使用了很长时间.

标签:spring,spring-java-config
来源: https://codeday.me/bug/20190711/1433792.html