Java 有没有办法在spring中重新加载自动连线实例或替换自动连线行为

Java 有没有办法在spring中重新加载自动连线实例或替换自动连线行为,java,spring,autowired,Java,Spring,Autowired,目前,我有一个在@Configuration中创建的bean,它从web下载json文档并创建一个模型对象。使用这个bean(自动连线),很多其他bean在启动时都会初始化 我需要一种在web中json文档发生更改时重新加载bean的方法 最好的方法是什么 代码: } @配置 @ComponentScan(basePackages=“com.wellmanager.prism”) 公共类PrismDataSourceConfig实现DataSourceConfig{ 私有最终记录器LOG=Log

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

我需要一种在web中json文档发生更改时重新加载bean的方法

最好的方法是什么

代码:

}

@配置
@ComponentScan(basePackages=“com.wellmanager.prism”)
公共类PrismDataSourceConfig实现DataSourceConfig{
私有最终记录器LOG=LoggerFactory.getLogger(PrismDataSourceConfig.class);
@自动连线
私人环境;
@自动连线
私有模型;
@初级的
@Bean(name=“itdb_数据源”)
公共数据源getDataSource(){
LOG.info(“getDataSource()”);
返回getDataSource(“itdb”);
}
@Bean(name=“dataSourceMap”)
公共地图getDataSourceMap(){
LOG.info(“getDataSourceMap()”);
Map dataSourceMap=Maps.newHashMap();
getDatabases().forEach((名称,数据库)->{
端点=getEndpoint(名称);
DataSource DataSource=createDataSource(端点);
dataSourceMap.put(名称、数据源);
});
返回数据源地图;
}
@Bean(name=“jdbcTemplateMap”)
公共映射getJdbcTemplateMap(){
LOG.info(“getDataSource()”);
Map jdbcTemplateMap=Maps.newHashMap();
getDataSourceMap().forEach((名称,数据源)->{
JdbcTemplate JdbcTemplate=新的JdbcTemplate(数据源);
put(名称,jdbcTemplate);
});
返回jdbcTemplateMap;
}
@凌驾
公共环境{
回归环境;
}
@凌驾
公共模型getModel(){
收益模型;
}

}自动连接是应用程序启动阶段(或类似的范围,如会话和请求)的一个概念。即使您找到了解决方案,您也在滥用spring概念并自找麻烦

因此,您应该改为使用Spring事件来更新单个bean的内容,该bean的内容不会发生更改,如下所示:

1) 编写类监视器以监视资源的更改

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


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

您的方法是非常错误的。自动连接用于在启动时连接依赖项。(实际上,现在不鼓励使用构造函数参数注入。)

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

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

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

<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>

10

您尝试过吗?它不会刷新整个上下文吗?我只想刷新bean及其依赖项?是的,这将刷新整个上下文。试图刷新其中的一部分听起来像是自找麻烦。我不知道你的确切情况,但对我来说,这听起来很像设计问题——我会尝试重新设计,以便当远程资源改变时应用程序上下文不需要改变。还有一件事要考虑——可能有“父”和“子”上下文,父上下文的bean在子上下文中可用。这样,您可以将不需要更改的bean与需要更改的bean分开。然后您可以只刷新子上下文。我添加了代码片段供您参考,每当外部配置更改时,我需要重新创建模型,并且我没有父/子上下文(不确定如何创建,因为此模型和数据源使用非常广泛)。如果可能的话,我可以改为基于工厂bean的方法,但不确定如何在代码中合并。
@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;
}
@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
}
<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>