java - Spring /SPeL : condition specific Cache control from one class to another

标签 java spring spring-el

tl;博士;

我正在寻找一种方法来在另一个类的 Spring Cacheable 注释上设置“条件”属性。有这样的办法吗?

使用 Spring Cache,它应该仅在调用某个方法时进行缓存。这个方法在ClassA中,要缓存的方法(数据)在ClassB中。我想做的是这样的:

public ClassA implements myInterface {
...  
    private Boolean inProcess = false;

    public void cacheWhenThisMethodCalled() {
        try {
            inProcess = true;
            // do work here, somewhere along the line
            // the method in ClassB gets called
        } finally {
            inProcess = false;
        }
 }

B类:

public ClassB {
...
    @Cacheable(cacheNames={"aCache"}, condition="#classA.inProcess")
    public ValueClass findValueClass(UUID id)

但是,我找不到 SPeL 工作的合适条件。我尝试了很多组合,但没有成功。 ClassA 是一个 SpringBean,但是 @Bean 注解返回的是 Interface,而不是类。这可以发挥作用吗?或者有更好的办法吗?

最佳答案

使用ThreadLocal - 为了线程安全,无论如何你都需要这样做 - 否则不同的线程可以更改该字段。

这很好用...

@SpringBootApplication
@EnableCaching
public class So47580936Application {

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

    @Bean
    public ApplicationRunner runner(Bar bar) {
        return args -> {
            bar.cacheFromHere();
            bar.dontCacheFromHere();
        };
    }

    @Component
    public static class Foo {

        @Cacheable(cacheNames = "foos", condition = "T(com.example.So47580936Application$Bar).cacheit()")
        public String foo() {
            System.out.println("here");
            return "foo";
        }

    }

    @Component
    public static class Bar {

        private static final ThreadLocal<Boolean> cacheit = new ThreadLocal<>();

        @Autowired
        private Foo foo;

        public static boolean cacheit() {
            return cacheit.get() == null ? false : cacheit.get();
        }

        public void cacheFromHere() {
            try {
                this.cacheit.set(true);
                System.out.println("Cache:" + this.foo.foo());
                System.out.println("Cache:" + this.foo.foo());
            }
            finally {
                this.cacheit.remove();
            }
        }

        public void dontCacheFromHere() {
            System.out.println("Don't:" + this.foo.foo());
            System.out.println("Don't:" + this.foo.foo());
        }

    }

}

结果:

here
Cache:foo
Cache:foo
here
Don't:foo
here
Don't:foo

编辑

或者,您可以将 ThreadLocal 设为 @Bean ...

@SpringBootApplication
@EnableCaching
public class So47580936Application {

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

    @Bean
    public ApplicationRunner runner(Bar bar) {
        return args -> {
            bar.cacheFromHere();
            bar.dontCacheFromHere();
        };
    }

    @Bean
    public ThreadLocal<Boolean> cacheit() {
        return new ThreadLocal<>();
    }

    @Component
    public static class Foo {

        @Cacheable(cacheNames = "foos", condition = "@cacheit.get() ?: false")
        public String foo() {
            System.out.println("here");
            return "foo";
        }

    }

    @Component
    public static class Bar {

        @Autowired
        private ThreadLocal<Boolean> cacheit;

        @Autowired
        private Foo foo;

        public void cacheFromHere() {
            try {
                this.cacheit.set(true);
                System.out.println("Cache:" + this.foo.foo());
                System.out.println("Cache:" + this.foo.foo());
            }
            finally {
                this.cacheit.remove();
            }
        }

        public void dontCacheFromHere() {
            System.out.println("Don't:" + this.foo.foo());
            System.out.println("Don't:" + this.foo.foo());
        }

    }

}

关于java - Spring /SPeL : condition specific Cache control from one class to another,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47580936/

相关文章:

java - 在 Spring EL 中引用当前 bean 的属性

java - 如何在 PreAuthorize 中解析属性文件中的属性?

Java类困惑

java - MyBatis 动态 ResultMap。如何返回不同POJO对象的列表?

java - 正则表达式确定文本中某个单词的出现次数是否不超过 n 次

Java Spring Tomcat : Custom DataSource Factory Being Ignored

spring - 如何评估自定义 java 代码中的 SpEL 安全表达式?

java - 如何获取Spring库来搭建Spring环境?

java - Spring 表单绑定(bind)怎么做呢?无法将类型 [java.lang.String] 的值转换为所需类型

java - HttpClient 支持多种 TLS 协议(protocol)