首页 > 解决方案 > Spring - 如何使用 aspectJ 缓存自调用?

问题描述

谢谢你点击我的问题。我想在自调用中调用缓存方法,所以需要使用AspectJ。(缓存的配置没问题)

  1. 添加 AspectJ 依赖项
implementation 'org.springframework.boot:spring-boot-starter-aop'
  1. 将 @EnableCaching(mode = AdviceMode.ASPECTJ) 添加到我的 application.java
@EnableJpaAuditing
@EnableCaching(mode = AdviceMode.ASPECTJ) // <-- here 
@SpringBootApplication
public class DoctorAnswerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DoctorAnswerApplication.class, args);
    }

}
  1. 我的服务.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)通过 AspectJ 而不是 Spring AOP(proxy) 使 @Cacheable 工作。

标签: springcachingaspectjehcachespring-aop

解决方案


感谢@kriegaex,他通过指出 spring-aspects 依赖和 load-time-weaving javaagent 要求来修复我。为了方便其他人,Spring Boot 和 Maven 的配置片段如下。

(注意:最后,我觉得这一切(以及副作用)对于我的项目来说并不值得。请参阅我的另一个答案,了解一个简单但有点难看的解决方法。)

聚甲醛:

    <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>

应用配置:

@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
public class ApplicationConfig { ... }

目标方法:

@Cacheable(cacheNames = { "cache-name" })
public Thingy fetchThingy(String identifier) { ... }

编织机制:

选项 1:加载时间编织(Spring 默认)

使用 JVM javaagent 参数或添加到您的 servlet 容器库

-javaagent:<path-to-jar>/aspectjweaver-<version>.jar

选项 2:编译时编织

(这应该是可行的,但我发现缺少与 Spring Caching 一起使用的连贯示例 - 请参阅下面的进一步阅读)

使用aspectj-maven-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

更多阅读:


推荐阅读