[英]Is there way to reload autowired instance or replace autowired behavior in spring
目前我有一個在@Configuration中創建的bean,它從web下載json文檔並創建一個模型對象。 使用這個bean(autowired),很多其他bean在啟動時被初始化
每當json文檔在Web中發生變化時,我都需要一種方法來重新加載bean。
最好的方法是什么?
碼:
@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);
}
}
}
@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
,它從遠程服務中檢索數據模型。 然后,您可以在需要它的類中注入此服務以獲取模型。
然后,您還可以使用像EhCache這樣的緩存,並在方法中添加注釋@Cacheable
,這樣您每次需要其他類時都不會從遠程源獲取模型。 (您可以在刷新數據之前配置ehcache.xml
以了解緩存的生存時間)。
@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分鍾后過期:
<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>
自動裝配是應用程序啟動階段(或會話和請求等類似范圍)的概念。 即使您找到了解決方案,您也在濫用彈簧概念並遇到麻煩。
因此,您應該使用Spring Events來更新不會更改的單個bean的內容,與此答案相同: https : //stackoverflow.com/a/4188343/2986984 :
1)編寫一個類監視器來監視資源的變化。
2)每當文件/資源發生變化時,讓該文件系統監視器觸發自定義Spring ApplicationEvent
3)讓您想要更新的bean實現ApplicationEventListener並在捕獲事件時重新加載資源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.