谢谢你点击我的问题。我想在自调用中调用一个缓存方法,所以我需要使用AspectJ。(缓存的配置是可以的)
1.添加AspectJ依赖项
implementation 'org.springframework.boot:spring-boot-starter-aop'
1.将@EnableCaching(模式=建议模式. ASPECTJ)添加到我的www.example.com application.java
@EnableJpaAuditing
@EnableCaching(mode = AdviceMode.ASPECTJ) // <-- here
@SpringBootApplication
public class DoctorAnswerApplication {
public static void main(String[] args) {
SpringApplication.run(DoctorAnswerApplication.class, args);
}
}
1.我的网站 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);
}
}
1.我的测试代码
@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 AOP(代理)工作。
4条答案
按热度按时间sz81bmfz1#
感谢@kriegaex,他指出了spring-aspects依赖性和load-time-weaving javaagent需求,为方便其他人,下面是Spring Boot和Maven的配置片段。
(Note:最后,我觉得这一切(以及副作用)对我的项目来说都不值得。请看我的另一个答案,一个简单的,但有点丑陋的解决方案。)
POM:
应用程序配置:
目标方法:
织造机构:
选项1:加载时间编织(Spring默认值)
使用JVM javaagent参数或添加到Servlet容器库中
选项2:编译时编织
(This应该是有效的,但我发现缺乏与Spring缓存一起使用的连贯示例-请参阅下面的进一步阅读)
使用aspectj-maven插件:https://www.mojohaus.org/aspectj-maven-plugin/index.html
出于参考/搜索目的,以下是启动这一切的错误:
更多阅读:
j5fpnvbx2#
你看过Javadoc for
EnableCaching
了吗?注意,如果mode()被设置为
AdviceMode.ASPECTJ
,那么proxyTargetClass()
属性的值将被忽略。还注意,在这种情况下,spring-aspects
模块JAR必须存在于类路径中,编译时编织或加载时编织将方面应用于受影响的类。在这种情况下不涉及代理;本地呼叫也将被拦截。所以请检查一下
1.在类路径上具有
spring-aspects
,并且1.使用参数
java -javaagent:/path/to/aspectjweaver.jar
启动应用程序。还有一种方法可以替代第二种方法,但是使用Java代理是最简单的。我不是Spring用户,所以我不是Spring配置Maven,但是即使像我这样的Spring新手也成功地使用了Java代理,所以请先给予一下。
6ojccjat3#
TL; DR:如果AspectJ让你头疼,而且除了解决Spring Caching自调用之外,你并不真正需要它,那么添加一个简单的服务层可以重用的"缓存委托" bean实际上可能会更干净/更轻/更容易。没有额外的依赖关系,没有性能影响,也没有改变Spring代理默认工作方式的意外副作用。
代码:
我再补充一个答案,因为为了解决我自己的这个问题,我最终改变了方向。@kriegaex和我自己在前面提到了更直接的解决方案,但对于那些在根本不需要AspectJ时无法使用它的人来说,这是一个不同的选择。
对于我的项目来说,添加AspectJ只允许可缓存的相同bean引用是一个灾难,它导致了10个新的头痛问题,而不是一个简单的(但令人讨厌的)问题。
简要的非详尽纲要如下:
最后,我又回到了Spring Caching by proxy,并引入了一个我的两个服务方法都可以引用的"缓存委托"。这个解决方案不是最好的,但对我来说,它比我在真正不需要AspectJ时跳过的所有AspectJ环都要好。我只想要无缝缓存和DRY服务代码,这正是这个解决方案所实现的。
9jyewag04#
经过大量的研究,我得到了使用编译时编织、 Boot 和jdk 17的自调用缓存方法。
我在Spring配置中需要的唯一注解是:
不需要@启用加载时间编织和@启用方面JAutoProxy。
这些是pom.xml的相关部分(dev.aspectj:aspectj-maven-plugin seams是唯一一个可以与最新java版本一起工作的部分):