首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有办法在spring中重新加载自动连接的实例或替换自动连接的行为?

有没有办法在spring中重新加载自动连接的实例或替换自动连接的行为?
EN

Stack Overflow用户
提问于 2019-05-17 14:56:53
回答 2查看 1.4K关注 0票数 1

目前,我有一个在@Configuration中创建的bean,它从web上下载json文档并创建一个模型对象。使用此bean (自动连接),在启动时初始化许多其他bean

每当json文档在web中发生变化时,我需要一种重新加载bean的方法。

做这件事最好的方法是什么?

代码:

代码语言:javascript
复制
@Configuration
@ComponentScan(basePackages = "com.wellmanage.prism")
public class PrismConfig {

...
@Bean
public Model model(@Qualifier("prismRestTemplate") RestTemplate restTemplate) {

    LOG.info("model()");
    MetadataReader metadataReader = new MetadataReader();
    String prismFormatJson = null;
    if (!isHasLatestTransformedJson()) {
        prismFormatJson = metadataReader.transformToPrismJson(restTemplate, environment);
        setLastGoodPrismConfiguration(prismFormatJson);
    } else {
        prismFormatJson = getLastGoodPrismConfiguration();
    }
    if (model != null) {
        return model;
    } else {
        return metadataReader.createModelForPrism(prismFormatJson);
    }
}

}

代码语言:javascript
复制
@Configuration
@ComponentScan(basePackages = "com.wellmanage.prism")
public class PrismDataSourceConfig implements DataSourceConfig {

private final Logger LOG = LoggerFactory.getLogger(PrismDataSourceConfig.class);

@Autowired
private Environment environment;

@Autowired
private Model model;

@Primary
@Bean(name = "itdb_dataSource")
public DataSource getDataSource() {

    LOG.info("getDataSource()");
    return getDataSource("itdb");
}

@Bean(name = "dataSourceMap")
public Map<String, DataSource> getDataSourceMap() {

    LOG.info("getDataSourceMap()");

    Map<String, DataSource> dataSourceMap = Maps.newHashMap();
    getDatabases().forEach((name, database) -> {
        Endpoint endpoint = getEndpoint(name);
        DataSource dataSource = createDataSource(endpoint);
        dataSourceMap.put(name, dataSource);
    });

    return dataSourceMap;
}

@Bean(name = "jdbcTemplateMap")
public Map<String, JdbcTemplate> getJdbcTemplateMap() {

    LOG.info("getDataSource()");

    Map<String, JdbcTemplate> jdbcTemplateMap = Maps.newHashMap();
    getDataSourceMap().forEach((name, datasource) -> {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
        jdbcTemplateMap.put(name, jdbcTemplate);
    });

    return jdbcTemplateMap;
}

@Override
public Environment getEnvironment() {

    return environment;
}

@Override
public Model getModel() {

    return model;
}

}

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-17 18:10:16

你的方法是非常错误的。自动装配用于在启动时连接依赖项。(这几天实际上不鼓励这样做,而是支持构造函数参数注入。)

您可能需要一个从远程服务检索数据模型的@Service。然后将此服务注入到需要它来获取模型的类中。

然后,您还可以使用像EhCache这样的缓存,并将注释@Cacheable添加到您的方法中,这样您就不会在每次其他类需要模型时都从远程源获取模型。(您可以在刷新数据之前配置您希望缓存存在的时间长度的ehcache.xml )。

代码语言:javascript
复制
@Service
public class ModelService {

  private final RestTemplate restTemplate;

  public ModelService(RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
  }

  @Cacheable(value = "model", key = "#root.methodName")
  public Model getModel() {

    MetadataReader metadataReader = new MetadataReader();
    String prismFormatJson = null;
    if (!isHasLatestTransformedJson()) {
        prismFormatJson = metadataReader.transformToPrismJson(restTemplate, environment);
        setLastGoodPrismConfiguration(prismFormatJson);
    } else {
        prismFormatJson = getLastGoodPrismConfiguration();
    }
    if (model != null) {
        return model;
    } else {
        return metadataReader.createModelForPrism(prismFormatJson);
    }
  }

  //... the rest of the code
}

这里我们将缓存配置为在10分钟后过期:

代码语言:javascript
复制
<config
  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
  xmlns='http://www.ehcache.org/v3'
  xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
  xsi:schemaLocation="
  http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
  http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

  <service>
    <jsr107:defaults>
      <jsr107:cache name="model" template="model-cache"/>
    </jsr107:defaults>
  </service>

  <cache-template name="model-cache">
    <expiry>
      <ttl unit="minutes">10</ttl>
    </expiry>
  </cache-template>
</config>
票数 2
EN

Stack Overflow用户

发布于 2019-05-17 18:04:28

自动装配是应用程序启动阶段(或类似的作用域,如会话和请求)的概念。即使你找到了解决方案,你也是在滥用弹簧概念并自找麻烦。

因此,您应该使用Spring Events来更新不变的单个bean的内容,就像下面的答案一样:https://stackoverflow.com/a/4188343/2986984

1)编写一个类监视器来监视资源的更改。

2)让文件系统监视器在文件/资源发生变化时触发自定义Spring ApplicationEvent

3)让您想要更新的bean实现ApplicationEventListener,并在它捕获到您的事件时重新加载资源。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56181130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档