[英]Spring boot: Managing bean scope “manually” for dynamically creating beans at runtime with differing states. Is there a problem with our solution?
So we essentially want to have a generic JDBC repo which can be instantiated with different database details at run-time. 因此,我们本质上希望有一个通用的JDBC存储库,该存储库可以在运行时用不同的数据库详细信息实例化。 Currently the setup is essentially " Get a GenericRepo bean with the details x, y, z. If a bean exists with those details, use that bean instead and use already existing one. If it doesn't exist, create it."
当前的设置基本上是“获取带有详细信息x,y,z的GenericRepo bean。如果存在具有这些详细信息的bean,请改用该bean并使用已经存在的bean。如果不存在,请创建它。”
This seems like the sort of things custom scopes could be used for, but is there anything inherently "wrong" with our solution that might cause issues? 这似乎是自定义范围可用于的事情,但是我们的解决方案有内在的“错误”之处,可能会引起问题吗?
This is a web app that may have multiple people using the GenericRepo at once. 这是一个Web应用程序,可能有多个人一次使用GenericRepo。
The Repo 回购
@Component
public class GenericDatabaseDAO {
JdbcTemplate data;
public GenericDatabaseDAO() {}
public GenericDatabaseDAO(String username, String password, String url, String driver) {
this.data = new JdbcTemplate(
DataSourceBuilder.create()
.username(username)
.password(password)
.url(url)
.driverClassName(driver)
.build()
);
}
public GenericDatabaseTableModel runQuery(String query) {
return new GenericDatabaseTableModel(data.queryForList(query));
}
@Service
public static class DAOService implements ApplicationContextAware {
ApplicationContext context;
AutowireCapableBeanFactory factory;
HashMap<String,GenericDatabaseDAO> beans = new HashMap<String,GenericDatabaseDAO>();
public GenericDatabaseDAO getDAO(String username, String password, String url, String driver) {
GenericDatabaseDAO dao = beans.get(username+'@'+url);
if(dao == null) {
dao = new GenericDatabaseDAO(username, password, url, driver);
factory.autowireBean(dao);
factory.initializeBean(dao, username+'@'+url);
beans.put(username+'@'+url, dao);
}
return dao;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.factory = context.getAutowireCapableBeanFactory();
}
}
}
How we use the repo 我们如何使用回购
//service class for running sql statements
@Autowired
GenericDatabaseDAO.DAOService factory;
public void runSqlOnDB(String username, String password, String url, String driver){
GenericDatabaseDAO gdbdao = factory.getDAO(username,password,url,driver);
gbdao.runQuery("sql here");
}
What you probably need to do, is look into @Configuration
annotations, so you can create new beans. 您可能需要做的就是查看
@Configuration
批注,以便创建新的bean。
@Bean
annotation makes sure that what is returned is a Spring bean. @Bean
批注确保返回的是Spring bean。 Finally, the @Scope
annotation tells Spring to create a new instance each time. 最后,
@Scope
注释告诉Spring每次创建一个新实例。
What I did not add, but which you can easily investigate is an @Cacheable
annotation to avoid multiple instances of a certain bean. 我没有添加,但是您可以轻松研究的是
@Cacheable
注释,以避免某个bean的多个实例。 Note: for caching you need some extra Spring jars in your Maven or Gradle. 注意:要进行缓存,您需要在Maven或Gradle中添加一些额外的Spring jar。 You also need
@EnableCaching
. 您还需要
@EnableCaching
。
@Configuration
public DaoFactory {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
// @Cacheable here !
public getDao(String name, String password, String url, String driver) {
return new GenericDatabaseDAO(name, password, url, driver);
}
}
If you want to use it, do something like 如果要使用它,请执行以下操作
@Autowired DaoFactory daoFactory;
...
GenericDatabaseDAO dao = daoFactory.getDao("user", "pwd", "url", "driver");
Sorry, I used @Autowired
because it made the example simpler :) 抱歉,我使用
@Autowired
因为它使示例更简单:)
Final note: you do not need an @Component
annotation on GenericDatabaseDAO
class. 最后说明:
GenericDatabaseDAO
类不需要@Component
批注。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.