以下是成功将数据持久保存在远程GemFire群集中并成功保持本地spring-cache更新的代码段。但是,当我尝试使用ExpirationAttributes
时,条目没有按预期的方式销毁。我已经提到了this和相关链接。任何建议都会有所帮助!
import org.springframework.data.gemfire.ExpirationActionType;
import org.springframework.data.gemfire.ExpirationAttributesFactoryBean;
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.support.GemfireCacheManager;
import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer;
@Configuration
@Profile("local")
public class GemFireCachingConfig {
@Bean
Properties gemfireProperties(...) {
//Sets gemfire properties and return
return gemfireProperties;
}
@Bean
@Primary
ReflectionBasedAutoSerializer reflectionBasedAutoSerializer() {
return new ReflectionBasedAutoSerializer("pkg.containing.cacheable.object");
}
@Bean
@Primary
ClientCacheFactoryBean clientCacheFactory(String injectedGemFirehost,
int injectedGemfirePort, Properties gemfireProperties,
ReflectionBasedAutoSerializer reflectionBasedAutoSerializer) {
ClientCacheFactoryBean cachefactoryBean = new ClientCacheFactoryBean();
cachefactoryBean.setProperties(gemfireProperties);
cachefactoryBean.setClose(true);
cachefactoryBean.setPdxSerializer(reflectionBasedAutoSerializer);
cachefactoryBean.setPdxReadSerialized(false);
cachefactoryBean.setPdxIgnoreUnreadFields(true);
ConnectionEndpoint[] locators = new ConnectionEndpoint[1];
locators[0] = new ConnectionEndpoint(injectedGemFirehost, injectedGemfirePort);
cachefactoryBean.setLocators(locators);
return cachefactoryBean;
}
@Bean
public ExpirationAttributesFactoryBean entryTtlExpirationAttributes(
int injectedTimeoutInSecs) {
ExpirationAttributesFactoryBean expirationAttributes = new ExpirationAttributesFactoryBean();
expirationAttributes.setAction(ExpirationActionType.DESTROY.getExpirationAction());
expirationAttributes.setTimeout(injectedTimeoutInSecs);
return expirationAttributes;
}
@Bean
@Autowired
public RegionAttributesFactoryBean regionAttributes(
@Qualifier("entryTtlExpirationAttributes") ExpirationAttributes entryTtl) {
RegionAttributesFactoryBean regionAttributes = new RegionAttributesFactoryBean();
regionAttributes.setStatisticsEnabled(true);
regionAttributes.setEntryTimeToLive(entryTtl);
return regionAttributes;
}
@Bean
@Primary
ClientRegionFactoryBean<String, Object> regionFactoryBean(ClientCache gemfireCache,
@Qualifier("regionAttributes") RegionAttributes<String, Object> regionAttributes) {
ClientRegionFactoryBean<String, Object> regionFactoryBean = new ClientRegionFactoryBean<>();
regionFactoryBean.setAttributes(regionAttributes);
regionFactoryBean.setCache(gemfireCache);
regionFactoryBean.setClose(false);
regionFactoryBean.setPersistent(false);
regionFactoryBean.setRegionName(regionName);
regionFactoryBean.setShortcut(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
return regionFactoryBean;
}
@Bean
GemfireCacheManager cacheManager(ClientCache gemfireCache) {
GemfireCacheManager cacheManager = new GemfireCacheManager();
cacheManager.setCache(gemfireCache);
return cacheManager;
}
}
最佳答案
只是好奇您如何认为injectedTimeoutInSeconds
是如何在Spring配置中“注入”到entryTtlExpirationAttributes
bean定义中的?这个...
@Bean
public ExpirationAttributesFactoryBean entryTtlExpirationAttributes(
int injectedTimeoutInSecs) {
ExpirationAttributesFactoryBean expirationAttributes =
new ExpirationAttributesFactoryBean();
expirationAttributes.setAction(
ExpirationActionType.DESTROY.getExpirationAction());
expirationAttributes.setTimeout(injectedTimeoutInSecs);
return expirationAttributes;
}
您需要使用Spring的
entryTtlExpirationAttributes
注释来注释@Value
bean定义方法参数(即,injectedTimeoutInSecs),就像这样...@Bean
public ExpirationAttributesFactoryBean entryTtlExpirationAttributes(
@Value("${gemfire.cache.expiration.ttl.timeout:600}")
int injectedTimeoutInSecs) {
然后,在Spring Boot
application.properties
文件中,可以为属性(gemfire.cache.expiration.ttl.timeout
)设置一个值。#application.properties
gemfire.cache.expiration.ttl.timeout = 300
如果未显式设置属性,则
@Value
注释可以提供默认值。@Value({${property:defaultValue}")
此外,您需要在Spring Java配置中提供
propertySourcePlaceholderConfigurer
bean定义,以使Spring能够“替换”属性占位符值...@Bean
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
您可以看到与here上方类似的配置。
最后,您可以将整个Spring GemFire Java配置类简化为该类。
import java.util.Collections;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
import org.springframework.data.gemfire.cache.config.EnableGemfireCaching;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheConfigurer;
import org.springframework.data.gemfire.config.annotation.EnablePdx;
import org.springframework.data.gemfire.expiration.ExpirationActionType;
import org.springframework.data.gemfire.expiration.ExpirationAttributesFactoryBean;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
@ClientCacheApplication
@EnableGemfireCaching
@EnablePdx(ignoreUnreadFields = true, readSerialized = false,
serializerBeanName = "reflectionBasedAutoSerializer")
@Profile("local")
public class GemFireCachingConfig {
@Bean
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
// NOTE: you can externalize Pivotal GemFire properties in a gemfire.properties file,
// placed in the root of your application classpath.
//
// Alternatively, you can use Spring Boot's application.properties to set GemFire properties
// using the corresponding Spring Data GemFire (annotation-based) property (e.g. spring.data.gemfire.cache.log-level)
//
// See here...
// https://docs.spring.io/spring-data/gemfire/docs/current/api/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#logLevel--
@Bean
@Primary
ReflectionBasedAutoSerializer reflectionBasedAutoSerializer() {
return new ReflectionBasedAutoSerializer("pkg.containing.cacheable.object");
}
@Bean
ClientCacheConfigurer clientCacheHostPortConfigurer(
@Value("gemfire.locator.host") String locatorHost,
@Value("gemfire.locator.port") int locatorPort) {
return (beanName, clientCacheFactoryBean) ->
clientCacheFactoryBean.setLocators(Collections.singletonList(
new ConnectionEndpoint(locatorHost, locatorPort)));
}
@Bean("RegionNameHere")
ClientRegionFactoryBean<String, Object> regionFactoryBean(GemFireCache gemfireCache,
@Qualifier("regionAttributes") RegionAttributes<String, Object> regionAttributes) {
ClientRegionFactoryBean<String, Object> clientRegionFactory = new ClientRegionFactoryBean<>();
clientRegionFactory.setAttributes(regionAttributes);
clientRegionFactory.setCache(gemfireCache);
clientRegionFactory.setClose(false);
clientRegionFactory.setShortcut(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
return clientRegionFactory;
}
@Bean
public RegionAttributesFactoryBean regionAttributes(
@Qualifier("entryTtlExpirationAttributes") ExpirationAttributes expirationAttributes) {
RegionAttributesFactoryBean regionAttributes = new RegionAttributesFactoryBean();
regionAttributes.setStatisticsEnabled(true);
regionAttributes.setEntryTimeToLive(expirationAttributes);
return regionAttributes;
}
@Bean
public ExpirationAttributesFactoryBean entryTtlExpirationAttributes(
@Value("${gemfire.cache.expiration:600") int timeoutInSeconds) {
ExpirationAttributesFactoryBean expirationAttributes = new ExpirationAttributesFactoryBean();
expirationAttributes.setAction(ExpirationActionType.DESTROY.getExpirationAction());
expirationAttributes.setTimeout(timeoutInSeconds);
return expirationAttributes;
}
}
当然,此配置基于Spring Data GemFire 2.0.1.RELEASE(Kay-SR1)。
注意
@ClientCacheApplication
批注,它替换了clientCacheFactory
bean定义的需要。我还使用了新的
@EnablePdx
注释来配置GemFire的PDX序列化行为。我声明了一个
ClientCacheConfigurer
类型的bean定义(clientCacheHostPortConfigurer
),以基于属性占位符动态调整Locator主机和端口配置。我定义了一个
PropertySourcesPlaceholderConfigurer
来处理整个基于Java的Spring配置元数据中@Value
批注中使用的属性占位符。我还使用了新的
@EnableGemfireCaching
注释,该注释替换了显式定义gemfireCacheManager
bean定义的需要。它还启用了Spring的Cache Abstraction(为您指定@EnableCaching
)。无论如何,SDG的新Annotation-based configuration model使其更易于执行所有操作。但是同样,您需要在Pivotal GemFire 9.1.x中使用Spring Data GemFire 2.0+(SD Kay)。
希望这可以帮助!
-约翰