有没有办法重新加载自动装配实例或替换 spring 中的自动装配行为
Is there way to reload autowired instance or replace autowired behavior in spring
目前我有一个在 @Configuration 中创建的 bean,它从 Web 下载 json 文档并创建一个模型对象。使用这个 bean(自动装配),许多其他 bean 在启动时初始化
我需要一种方法来在 Web 中 json 文档发生变化时重新加载 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;
}
}
自动装配是应用程序启动阶段(或会话和请求等类似范围)的概念。即使您找到了解决方案,您也是在滥用 spring 概念并自找麻烦。
所以您应该改用 Spring 事件来更新不会更改的单个 bean 的内容,与此答案相同::
1) 编写一个 class 监视器来监视资源的变化。
2) 让文件系统监视器在文件/资源更改时触发自定义 Spring ApplicationEvent
3) 让您想要更新的 bean 实现 ApplicationEventListener 并在它捕获您的事件时重新加载资源。
你的做法是非常错误的。自动装配用于在启动时连接依赖项。 (现在实际上不鼓励,支持构造函数参数注入。)
您可能需要的是 @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>
目前我有一个在 @Configuration 中创建的 bean,它从 Web 下载 json 文档并创建一个模型对象。使用这个 bean(自动装配),许多其他 bean 在启动时初始化
我需要一种方法来在 Web 中 json 文档发生变化时重新加载 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;
}
}
自动装配是应用程序启动阶段(或会话和请求等类似范围)的概念。即使您找到了解决方案,您也是在滥用 spring 概念并自找麻烦。
所以您应该改用 Spring 事件来更新不会更改的单个 bean 的内容,与此答案相同::
1) 编写一个 class 监视器来监视资源的变化。
2) 让文件系统监视器在文件/资源更改时触发自定义 Spring ApplicationEvent
3) 让您想要更新的 bean 实现 ApplicationEventListener 并在它捕获您的事件时重新加载资源。
你的做法是非常错误的。自动装配用于在启动时连接依赖项。 (现在实际上不鼓励,支持构造函数参数注入。)
您可能需要的是 @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>