springBoot Cache + aop self-invocation 问题

2023-10-17 04:31:36 +08:00
 bleulucaswu
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
@EnableCaching
public class StartupApplication { }

@Service
public class AccountService {

    @Cacheable(cacheNames = "accountsActivated", sync = true)
    public List<AccountDto> retrieveActivatedCacheable() { }
    
    public AccountDto retrieveActivatedByName(String name) { 
    // 这里 call retrieveActivatedCacheable() 不会从缓存中查询
    }

  1. aopContext.getCurrentProxy
    • ((AccountService) AopContext.currentProxy()).retrieveActivatedCacheable()
      • java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.
    • exposeProxy = true not in effect · Issue #16516 · spring-projects/spring-boot 跟这个 issue 基本一样,没有解决方案

  1. 两个方法放不同类
    • 最终方案,业务关联性强,放不同类没意义

  1. self-inject 和 Compile-time weaver Invoke Spring @Cacheable from Another Method of Same Bean | Baeldung
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 
public class AccountService
    @Autowired
    private AccountService self;

    @Cacheable(cacheNames = "accountsActivated", sync = true)
    public List<AccountDto> retrieveActivatedCacheable() { }
    
    public AccountDto retrieveActivatedByName(String name) {
       self.retrieveActivatedCacheable().....

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class demo.usul.dto.AccountDto (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; demo.usul.dto.AccountDto is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @5d339696)

--add-opens=java.base/java.time=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED

1485 次点击
所在节点    Java
8 条回复
leo97
2023-10-17 04:54:41 +08:00
self 加上 spring 的 @Lazy 试试呢?

private AccountService self;
wenbinwu
2023-10-17 05:04:09 +08:00
> 最终方案,业务关联性强,放不同类没意义
虽然这么说,可整一个 CachedAccountService 放所有 cached 方法不就完了
搁这事死磕浪费时间干啥
wenbinwu
2023-10-17 05:23:12 +08:00
关于 aspectj-maven-plugin , 用 dev.aspectj 的 https://github.com/dev-aspectj/aspectj-maven-plugin#history
xuanbg
2023-10-17 07:05:41 +08:00
class java.util.LinkedHashMap cannot be cast to class
zjp
2023-10-17 08:55:44 +08:00
自己注入自己,或者从容器手动获取自己都可以,真没必要死磕
jakes
2023-10-17 09:00:29 +08:00
同意二楼。这是最简单最常用的方法,死磕范式没什么意义。
banmuyutian
2023-10-17 09:47:12 +08:00
self 加个 @Lazy 就可以了,再不行从 SpringContext 里拿
bleulucaswu
2023-10-17 11:15:30 +08:00
@wenbinwu 试过这个 plugin ,花半天搞定了跟 lombok 兼容问题,找了个能支持 java17 的 aspectjrt runtime, 跑起来了,没用,不知道问题在哪... 所以我觉得这种 compile-time weaver 应该是最不推荐的方案

因为有空,就死磕了一下,没法子了,这问题超出我的能力范围了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/982613

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX