在使用Spring时,很多初学者不了解Spring对象注入的机制和面向切面编程的原理,很容易犯一些错误。下面就是初学者最容易犯的错误。举例如下:

@Component

public class TestClass {
    private Random random = new Random();
    @Cacheable("cache1")
    public String getData(String key){
        System.out.println("load data from file, key = " + key);
        return  key + key;
    }
    @Scheduled(fixedDelay = 100)
    public void task(){
        int rand = random.nextInt(100);
        String strParam = String.format("%d", rand);
        String str = getData(strParam);
        System.out.println("result is " + str);
    }
}

这里TestClass类里同时启用了Scheduled注解和@Cacheable注解。如果在外面其他类中调用getData(...)时,缓存机制会生效,但是在task函数内部调用getData(...)时,缓存机制不会生效。网上有人把这归纳为:不能在同一个类中互相调用注解过的方法,否则注解失效。

为什么会有这样的差别呢?背后的原因就是Spring的对象注入机制。

当外部通过@Autowired注解得到一个TestClass对象时,其实得到的是一个Spring包装过的代理对象。如下图所示。

当调用Obj.getData时,实际调用的是Spring的Proxy对象中的getData方法,该方法内置了Cache机制,在Cache检查后就会调用实际的TestClass对象中的getData方法。

同理通过@Scheduled注解表示这是一个任务调度时,Spring Proxy对象中会初始化对应的调度线程池等工作,当触发调度条件时,再调用实际的TestClass对象。

但是当在实际的TestClass对象中再调用getData时,不会触发Cache机制,因为此时不是调用的SpringCacheProxy对象,而是一个实际的TestClass对象,所以不会触发Cache机制。

如果大家深入去读Spring完成注入和AOP编程实现的原理,可以发现动态代理是很重要的一个技术。目前Spring的动态代理主要是通过CGLib来实现的。后面我会再写CGLib的实现思路。

那么我们该如何避免出现上述问题呢?

首先我们应该牢记一个原则:同一个类中的注解方法互相调用时,注解机制可能是无效的。

对于上述示例,我们可以把其拆分为两个类来实现,一个类完成任务调度、一个类完成Cache机制。这样在任务调度中调用的是Spring实现了Cache机制的代理类,可以确保其Cache机制生效。

转载于:https://www.cnblogs.com/shuzl/p/5304762.html

Spring同一个类中注解方法互相调用的问题相关推荐

  1. Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转)

    Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转) 参考文章: (1)Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转) (2)https://www. ...

  2. @transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...

    Spring注解(如@Transactional.@Cacheable.@Async等),在使用不当时,很可能会失效.失效的情况有很多种,本文我们就来瞅瞅,为啥同一个类中普通方法调用Spring注解方 ...

  3. spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效

    title: "spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效" url: "https://wsk1103.githu ...

  4. 【Python——类】 同一个类中一个函数里调用另一个函数的方法

    [Python-类] 同一个类中一个函数里调用另一个函数的方法 class Solution:def a(self):self.b() # 注意这种写法:self.类名def b(self):prin ...

  5. Python 同一个类中不同函数相互调用

    本文采取:Python的类中函数方法相互调用的两种方式_狗哥的博客-CSDN博客 __metaclass__=type class Stu:name=Noneage=Noneschool=" ...

  6. 梳理:python—同一个类中的方法调用

    为什么突然在此提到这个梳理问题呢? 因为在自己实践综合练习学过的知识时,突然觉得有些知识点的运用总是不成功,于是翻过课本进行回顾,总是觉得是对的,可是当再进一步思考"既然是对的,为什么在程序 ...

  7. 方法重载在同一个类中,方法名相同,参数不同,可以定义多个同名的方法根据不同的参数,可以调用不同的方法

    ```java /**  * 测试使用方法的重载  */ public class Test { public static void sum(int a,int b){         System ...

  8. java嵌套类中的方法怎么调用_java类与嵌套嵌套后,怎么使用最外层的类建立对象后使用内部类的方法?...

    展开全部 /* package whatever; // don't place package name! */ import java.util.*; import java.lang.*; im ...

  9. python类内部方法调用_python如何调用类中的方法

    调用同一个类中的方法 首先类中的方法在定义的时候需要先加参数self,例如:def SaveData(self,ip): print(ip)如果无self参数则不能在同一个类中调用(之前一直在这里犯错 ...

最新文章

  1. 《自然》预测2019年重大科学事件
  2. python划分代码_多分类评价指标python代码
  3. Java开发中JDBC连接数据库代码和步骤
  4. access中总计为first_用Access开发生产管理系统
  5. 技术动态 | 清华大学开源OpenKE:知识表示学习平台
  6. Linux内核分析 - 网络[五]:vlan协议-802.1q
  7. 两本关于sharepoint 2010的书值得参考
  8. 2015年中国互联网大检阅
  9. travis不生效,No builds for this repository
  10. 【“您未被授权查看该页”的原因和解决办法】
  11. MySQL 查询本月各周
  12. 计算机视觉可解释性——卷积神经网络中间层的可视化
  13. 互联网摸鱼日报(2022-12-25)
  14. 【Java基础】重写equals方法详讲
  15. POI锁定单元格的问题
  16. H.265/HEVC学习笔记:量化
  17. c语言计算n+nn+nnn+nnnn......---@颜麓
  18. SUSAN角点检测实现
  19. docker添加新的环境变量_Docker容器环境变量设置与查看
  20. 二维码生成器-客户端

热门文章

  1. oracle Lpad()函数和Rpad()函数的用法
  2. oracle查询:分组查询,取出每组中的第一条记录
  3. HTTP协议详细总结
  4. Java Servlet 和JSP教程(2)
  5. 信息系统安全等级保护备案任务详单
  6. nfs:server 172.168.1.22 not responding,still trying arm客户端配置
  7. [jQuery]Great Ways to Learn jQuery
  8. libevent 接收TCP连接
  9. ionic2+angular2中踩的那些坑
  10. Apache 及 Nginx 配置