谢谢你点击我的问题。我想在自调用中调用一个缓存方法,所以我需要使用AspectJ。(缓存的配置没有问题)
implementation 'org.springframework.boot:spring-boot-starter-aop'
在application.java中添加@EnableCaching(= AdviceMode.ASPECTJ)
@EnableJpaAuditing
@EnableCaching(mode = AdviceMode.ASPECTJ) // <-- here
@SpringBootApplication
public class DoctorAnswerApplication {
public static void main(String[] args) {
SpringApplication.run(DoctorAnswerApplication.class, args);
}
}
我的service.java
@Service
public class PredictionService {
@Cacheable(value = "findCompletedRecordCache")
public HealthCheckupRecord getRecordComplete(Long memberId, String checkupDate) {
Optional<HealthCheckupRecord> recordCheckupData;
recordCheckupData = healthCheckupRecordRepository.findByMemberIdAndCheckupDateAndStep(memberId, checkupDate, RecordStep.COMPLETE);
return recordCheckupData.orElseThrow(NoSuchElementException::new);
}
}
@Test
public void getRecordCompleteCacheCreate() {
// given
Long memberId = (long)this.testUserId;
List<HealthCheckupRecord> recordDesc = healthCheckupRecordRepository.findByMemberIdAndStepOrderByCheckupDateDesc(testUserId, RecordStep.COMPLETE);
String checkupDate = recordDesc.get(0).getCheckupDate();
String checkupDate2 = recordDesc.get(1).getCheckupDate();
// when
HealthCheckupRecord first = predictionService.getRecordComplete(memberId,checkupDate);
HealthCheckupRecord second = predictionService.getRecordComplete(memberId,checkupDate);
HealthCheckupRecord third = predictionService.getRecordComplete(memberId,checkupDate2);
// then
assertThat(first).isEqualTo(second);
assertThat(first).isNotEqualTo(third);
}
我没有.?我没有做任何与aspectJ相关的课程。我认为@EnableCaching(mode = AdviceMode.ASPECTJ)
使@Cacheable工作由AspectJ代替Spring (代理)。
发布于 2020-07-16 12:51:23
你读过Javadoc for EnableCaching
吗?
注意,如果mode()被设置为
AdviceMode.ASPECTJ
,那么proxyTargetClass()
属性值将被忽略。还请注意,在本例中,spring-aspects
模块JAR必须出现在类路径上,编译时编织或加载时编织将方面应用于受影响的类。在这种情况下不涉及代理;本地呼叫也将被截获。
所以请查查你
类路径上有java -javaagent:/path/to/aspectjweaver.jar
.,
spring-aspects
启动应用程序除了#2,还有一个替代方案,但使用Java代理是最简单的。我不是Spring用户,所以我不是Spring配置方面的专家,但即使像我这样的Spring也成功地使用了Java代理,所以请先试一试。
发布于 2020-11-24 21:38:29
感谢@kriegaex,他通过指出spring-方面的依赖关系和加载时编织javaagent的需求,修正了我的观点。为了方便其他人,Spring和Maven的配置片段如下。
(注:最后,我不觉得这一切(和副作用)值得我的项目。看看我的另一个答案,一个简单的,如果有点丑陋,解决办法。)
POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
应用程序Config:
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
public class ApplicationConfig { ... }
目标方法:
@Cacheable(cacheNames = { "cache-name" })
public Thingy fetchThingy(String identifier) { ... }
编织机构:
选项1:加载时间编织(Spring默认值)
使用javaagent参数或向servlet容器库添加
-javaagent:<path-to-jar>/aspectjweaver-<version>.jar
选项2:编译时编织
(据推测,这是可行的,但我发现缺乏用于Spring缓存的连贯示例-请参阅下面的进一步阅读)
使用aspectj plugin:https://www.mojohaus.org/aspectj-maven-plugin/index.html
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<showWeaveInfo>false</showWeaveInfo>
<Xlint>warning</Xlint>
<verbose>false</verbose>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
为了便于参考/搜索,下面是启动所有这些的错误:
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/cache/aspectj/AspectJCachingConfiguration.class] cannot be opened because it does not exist
更多阅读:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop
发布于 2020-11-30 18:35:51
TL;DR:如果AspectJ给您带来了麻烦,而您除了使用Spring缓存自调用之外,并不真正需要它,那么添加一个简单的“缓存委托”bean可能会更干净/更轻/更容易,这样您的服务层就可以重用它了。没有额外的依赖关系,没有性能影响,也没有意外的副作用来改变spring代理的默认工作方式。
代码:
@Component
public class CacheDelegateImpl implements CacheDelegate {
@Override @Cacheable(cacheNames = { "things" })
public Object getTheThing(String id) { ... }
}
@Service
public class ThingServiceImpl implements ThingService {
@Resource
private CacheDelegate cacheDelegate;
public Object getTheThing(String id) {
return cacheDelegate.getTheThing(id);
}
public Collection<Object> getAllTheThings() {
return CollectionUtils.emptyIfNull(findAllTheIds())
.parallelStream()
.map(this::getTheThing)
.collect(Collectors.toSet());
}
}
增加另一个答案,因为为了解决同样的问题,我最终改变了方向。前面的@kriegaex和我自己已经注意到了更直接的解决方案,但是对于那些在根本上不需要使用AspectJ的人来说,这是一个不同的选择。
对于我的项目来说,添加AspectJ只是为了允许缓存相同的bean引用,这是一场灾难,它导致了10个新的麻烦,而不是一个简单的(但令人讨厌的)问题。
一个简短的、并非详尽无遗的概述是:
dependencies
H114< )。versions)
对古代太阳微系统tools.jar的依赖(在后来的OpenJDK tools.jar中不存在)
通常都很糟糕,而且对如何在与Spring事务隔离的情况下实现缓存用例和/或没有使用AspectJ (我不需要/不想要的)
的完整AOP的问题进行了讨论。
最后,我通过代理返回Spring缓存,并引入了我的两个服务方法都可以引用的“缓存委托”。这个解决方案并不是最漂亮的,但对我来说,比我在真正不需要AspectJ时跳过的所有AspectJ箍都更好。我只想要无缝缓存和干服务代码,这个解决方案实现了这一点。
https://stackoverflow.com/questions/62932146
复制相似问题