简体   繁体   English

春季启动:“手动”管理bean作用域,以便在运行时以不同状态动态创建bean。 我们的解决方案有问题吗?

[英]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.

相关问题 Spring:使用@Bean 创建 bean - Spring : creating beans with @Bean Spring Boot管理接口Bean - Spring Boot Managing Interface Beans spring - 启动(创建 bean 时出错) - org.springframework.beans.factory.UnsatisfiedDependencyException:使用名称创建 bean 时出错 - spring - boot (error while creating beans ) - org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 如何在运行时使用 json 模式在 Spring Boot 中动态创建 bean - How to create a bean dynamically in spring boot using a json schema in runtime Spring启动创建bean错误 - Spring boot creating beans error Spring boot 创建名为“entityManagerFactory”的 bean 时出错。 是数据库问题吗? - Spring boot Error creating bean with name 'entityManagerFactory'. Is it a database problem? 错误org.springframework.beans.factory.BeanCreationException:创建bean Spring Boot时出错 - Error org.springframework.beans.factory.BeanCreationException: Error creating bean Spring Boot Spring Boot 项目“org.springframework.beans.factory.BeanCreationException:创建名为‘entityManagerFactory’的 bean 时出错”错误 - Spring Boot Project "org.springframework.beans.factory.BeanCreationException:Error creating bean with name 'entityManagerFactory'" ERROR Spring Boot`org.springframework.beans.factory.BeanCreationException:创建bean的错误注入自动绑定的依赖项失败; - Spring Boot `org.springframework.beans.factory.BeanCreationException: Error creating bean Injection of autowired dependencies failed; Spring 启动 BookStore 项目“org.springframework.beans.factory.BeanCreationException:创建名为“bookStoreRepo”的 bean 时出错” - Spring Boot BookStore Project "org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookStoreRepo'"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM