Spring/SPeL:条件特定的缓存控制从一个 class 到另一个
Spring/SPeL: condition specific Cache control from one class to another
tl;博士;
我正在寻找一种方法来在来自另一个 class 的 Spring 可缓存注释上设置 "condition" 属性。有这样的方法吗?
使用 Spring 缓存,它应该只在调用某个方法时缓存。该方法在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 工作的合适条件。我尝试了很多组合, none 成功了。 ClassA 是一个 SpringBean,但 @Bean 注释 returns 接口,而不是 class。这可以工作吗?或者有更好的方法吗?
使用 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());
}
}
}
tl;博士;
我正在寻找一种方法来在来自另一个 class 的 Spring 可缓存注释上设置 "condition" 属性。有这样的方法吗?
使用 Spring 缓存,它应该只在调用某个方法时缓存。该方法在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 工作的合适条件。我尝试了很多组合, none 成功了。 ClassA 是一个 SpringBean,但 @Bean 注释 returns 接口,而不是 class。这可以工作吗?或者有更好的方法吗?
使用 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());
}
}
}