我的问题与Spring的AspectJ模式有关,特别是如何启用它:
1)我注意到为了启用AspectJ模式进行事务管理,我只需要执行以下操作:
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
Run Code Online (Sandbox Code Playgroud)
2)为了使用AspectJ模式进行缓存,似乎必须:
- 将以下jar放入Tomcat的lib目录: - org.springframework:spring-instrument-tomcat
在Tomcat的server.xml中添加以下行:
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
Run Code Online (Sandbox Code Playgroud)
- 添加以下配置:
@Configuration
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
public class LoadTimeWeavingConfiguration implements LoadTimeWeavingConfigurer {
@Override
public LoadTimeWeaver getLoadTimeWeaver() {
return new ReflectiveLoadTimeWeaver();
}
}
Run Code Online (Sandbox Code Playgroud)
- 最终能够使用AspectJ模式如下:
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
Run Code Online (Sandbox Code Playgroud)
以上是对的吗?如果是这样,为什么AspectJ模式缓存与AspectJ模式事务支持不同?
与spring框架中的提交有关https://github.com/spring-projects/spring-framework/commit/5aefcc802ef05abc51bbfbeb4a78b3032ff9eee3
初始化设置为从afterPropertiesSet()到afterSingletonsInstantiated()的后续阶段
简而言之:这可以防止在@PostConstruct用例中使用缓存时缓存工作.
更长的版本:这可以防止您使用的用例
在methodB上使用@Cacheable创建serviceB
使用@PostConstruct调用serviceB.methodB创建serviceA
@Component
public class ServiceA{
@Autowired
private ServiceB serviceB;
@PostConstruct
public void init() {
List<String> list = serviceB.loadSomething();
}
Run Code Online (Sandbox Code Playgroud)这导致org.springframework.cache.interceptor.CacheAspectSupport现在不进行初始化,因此不会缓存结果.
protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
// check whether aspect is enabled
// to cope with cases where the AJ is pulled in automatically
if (this.initialized) {
//>>>>>>>>>>>> NOT Being called
Class<?> targetClass = getTargetClass(target);
Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);
if (!CollectionUtils.isEmpty(operations)) { …
Run Code Online (Sandbox Code Playgroud) 我想要动态缓存名称,spring 4.1 允许这样做
从 Spring 4.1 开始,缓存注释的 value 属性不再是强制性的,因为无论注释的内容如何,CacheResolver 都可以提供此特定信息。
请注意我如何偏执地设置cacheResolver
所有可能的级别:
@Cacheable(cacheResolver = "defaultCacheResolver")
@CacheConfig(cacheResolver = "defaultCacheResolver")
public interface GatewayRepository extends CrudRepository<Gateway, Integer> {
@Cacheable(cacheResolver = "defaultCacheResolver")
Gateway findByBulkId(int bulkId);
}
Run Code Online (Sandbox Code Playgroud)
Spring 4.1.5 仍然无法验证配置并出现错误:Caused by: java.lang.IllegalStateException: No cache names could be detected on 'public abstract skunkworks.data.Gateway skunkworks.repos.GatewayRepository.findByBulkId(int)'. Make sure to set the value parameter on the annotation or declare a @CacheConfig at the class-level with the default cache name(s) to use.
at org.springframework.cache.annotation.SpringCacheAnnotationParser.validateCacheOperation(SpringCacheAnnotationParser.java:240)
我正在尝试在Spring @Cache注释中使用Java 8流和lambda表达式.
我正在尝试使用以下内容:
@CacheEvict(value = "tags", allEntries = true,
condition = "#entity.getTags().stream().anyMatch(tag -> tag.getId() == null)")
Run Code Online (Sandbox Code Playgroud)
失败的是:
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
org.springframework.expression.spel.SpelParseException:
EL1042E:(pos 40): Problem parsing right operand
Run Code Online (Sandbox Code Playgroud)
但是,如果我将流移动到实体上的方法中,我能够使它工作.然后注释如下工作,没有错误:
@CacheEvict(value = "tags", beforeInvocation=true, allEntries = true,
condition = "#entity.containsNewTag()")
Run Code Online (Sandbox Code Playgroud)
我宁愿不需要'containtsNewTag()'方法,如果可能的话,直接在SpEL表达式中使用流.可以这样做吗?
我想使用Spring的Cache抽象将方法注释为@Cacheable。但是,某些方法被设计为采用参数的数组或集合并返回一个集合。例如,考虑使用以下方法查找实体:
public Collection<Entity> getEntities(Collection<Long> ids)
Run Code Online (Sandbox Code Playgroud)
从语义上讲,我需要Entity
单独缓存对象(由id键),而不是基于整个ID的集合。类似于这个问题在问什么。
简单的Spring Memcached通过其支持了我想要的ReadThroughMultiCache
,但是我想使用Spring的抽象来支持轻松更改缓存存储实现(Guava,Coherence,Hazelcast等),而不仅仅是memcached。
有哪些策略可以使用Spring Cache缓存这种方法?
考虑一个可以插入和检索对象并使用Spring缓存抽象的服务类,如何以返回Optional的方式注释方法?
class MyServiceImpl implements MyService {
private static final String CACHE_NAME = "itemCache";
@Override
@Cacheable(CACHE_NAME)
public Optional<Item> findById(Long id) {
// access the repository to retrieve the item
}
@Override
@CachePut(cacheNames = CACHE_NAME, key = "#item.id")
public Item insertItem(Item item) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,ClassCastException
抛出了a ,因为insertItem
将Item
实例放入缓存中,并findById
期望Optional
可能包含Item
实例.
我正在使用Spring Boot和EhCache开发日历应用程序。我正在尝试缓存以下方法:
@Override
@Cacheable(value = "concerts")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}
Run Code Online (Sandbox Code Playgroud)
挑战是我想操纵返回的缓存结果。例如,检查是否存在给定日期但另一个用户的缓存,然后取而代之(只要两个用户都符合特定条件)。
因此,在返回结果之前,我想:
我认为最好的办法是创建一个自定义缓存管理器,该缓存管理器将对缓存的Concert执行所有操作,并对所有其他方法使用默认的自动配置的缓存,但是我无法让我的自定义管理器正常工作并且没有发现任何好处如何实现自定义CacheManager的示例。
这是我所拥有的:
Application.java:
@SpringBootApplication
@ComponentScan
@EnableCaching
@EnableScheduling
public class SpringBootWebApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootWebApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<SpringBootWebApplication> applicationClass = SpringBootWebApplication.class;
@Bean(name = "eventsCacheManager")
public EventsCacheManager eventsCacheManager() {
return new EventsCacheManager();
}
@Primary
@Bean(name = "cacheManager") …
Run Code Online (Sandbox Code Playgroud) 我在SpringBootApplication中实现了缓存,如下所示
@SpringBootApplication
@EnableCaching
public class SampleApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SampleApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
Run Code Online (Sandbox Code Playgroud)
这绝对是正常的.
但是要实现缓存,应该定义一个必需的CacheManager/Cacheprovider.没有定义任何cacheManager也我的应用程序工作正常.
是否有Spring定义的默认缓存管理器?Spring文档说Spring Boot自动配置一个合适的CacheManager.
那么如果我们不定义CacheManager会使用什么呢?
有一个用@Cacheable注释的方法返回一个对象:
@Service
public class UserService {
@Cacheable("userData")
public UserData getUserData(String userName) {
UserData userData = new UserData();
userData.setGotFromCache(false);
return userData;
}
}
Run Code Online (Sandbox Code Playgroud)
和 UserData 对象:
@Getter
@Setter
public class UserData {
private boolean gotFromCache;
}
Run Code Online (Sandbox Code Playgroud)
如何检测@Cacheable注解的方法是否被调用或者其输出是否来自缓存?
解决方法是注入 CacheManager 并手动检测它:
Cache cache = this.cacheManager.getCache("userData");
UserData userData = null;
String userName = "some user name";
if (cache != null) {
Object key = SimpleKeyGenerator.generateKey(userName);
userData = cache.get(key, UserData.class);
if (userData != null) {
userData.setGotFromCache(true);
} else {
userData = userService.getUserData(userName);
cache.put(key, userData); …
Run Code Online (Sandbox Code Playgroud) 是否可以将咖啡因CacheLoader::loadAll
与@Cacheable
带有集合参数的带注释方法一起使用,例如
@Cacheable(cacheNames = "exampleCache", cacheManager="exampleCacheManager", keyGenerator = "complexKeyGenerator")
List<String> getItems(List<String> keys, String commonForEveryKey) {
return ...
}
@Component
class ComplexKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return ((List<String>)params[0]).stream()
.map(item -> new ComplexKey(item, (String) params[1]))
.collect(Collectors.toList());
}
}
@Data
@AllArgsConstructor
class ComplexKey {
String key;
String commonGuy;
}
class CustomCacheLoader implements CacheLoader<ComplexKey, String> {
@Override
public @Nullable String load(@NonNull ComplexKey key) throws Exception {
return loadAll(List.of(key)).get(key);
}
@Override
public @NonNull …
Run Code Online (Sandbox Code Playgroud) spring-cache ×10
spring ×6
java ×3
spring-boot ×3
caching ×2
ehcache ×2
aspectj ×1
spring-aop ×1
spring-data ×1
spring-el ×1