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