Spring boot: управление областью компонентов "вручную" для динамического создания компонентов во время выполнения с различными состояниями.Есть ли проблема с нашим решением? - PullRequest
0 голосов
/ 02 июля 2019

Таким образом, мы, по сути, хотим иметь общее репозиторий JDBC, который может быть создан с различными деталями базы данных во время выполнения. В настоящее время настройка по сути состоит в том, чтобы «получить бин GenericRepo с деталями x, y, z. Если бин существует с этими деталями, используйте этот боб вместо этого и используйте уже существующий. Если он не существует, создайте его».

Это похоже на то, для чего можно использовать пользовательские области, но есть ли что-то изначально "неправильное" в нашем решении, которое может вызвать проблемы?

Это веб-приложение, в котором может быть несколько человек, использующих GenericRepo одновременно.

Репо

@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();
    }

}
 }

Как мы используем репо

//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");

 }

1 Ответ

1 голос
/ 02 июля 2019

Что вам, вероятно, нужно сделать, это посмотреть на @Configuration аннотации, чтобы вы могли создавать новые bean-компоненты.

@Bean аннотация гарантирует, что возвращается возвращаемый бин Spring. Наконец, аннотация @Scope сообщает Spring, чтобы каждый раз создавать новый экземпляр.

То, что я не добавил, но вы можете легко исследовать, это аннотация @Cacheable, чтобы избежать нескольких экземпляров определенного компонента. Примечание: для кеширования вам понадобятся дополнительные баночки Spring в вашем Maven или Gradle. Вам также нужно @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);
   }

}

Если вы хотите использовать это, сделайте что-то вроде

@Autowired DaoFactory daoFactory;
... 

GenericDatabaseDAO dao = daoFactory.getDao("user", "pwd", "url", "driver");

Извините, я использовал @Autowired, потому что это упростило пример:)

Последнее замечание: вам не нужна аннотация @Component для GenericDatabaseDAO класса.

...