`
JerryWang_SAP
  • 浏览: 1029337 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

Java注解@Cacheable的工作原理

阅读更多

In order to avoid unnecessary query on database it is a common pattern to define a cache in application layer to cache the query result from database. See one example below. Here the application cache is maintained in a custom class CacheContext.

public class AccountService1 {
    private final Logger logger = LoggerFactory.getLogger(AccountService1.class);

    private CacheContext<Account> accountCacheContext;

    public Account getAccountByName(String accountName) {
        Account result = accountCacheContext.get(accountName);
        if (result != null) {
            logger.info("get from cache... {}", accountName);
            return result;
        }

        Optional<Account> accountOptional = getFromDB(accountName);
        if (!accountOptional.isPresent()) {
            throw new IllegalStateException(String.format("can not find account by account name : [%s]", accountName));
        }

        Account account = accountOptional.get();
        accountCacheContext.addOrUpdateCache(accountName, account);
        return account;
    }

In Spring there is an annotation @Cacheable which can make the cache managed by Spring instead of application developer. See improved version:

public class AccountService2 {

    private final Logger logger = LoggerFactory.getLogger(AccountService2.class);

    @Cacheable(value="accountCache")
    public Account getAccountByName(String accountName) {
        logger.info("in method getAccountByName, querying account... {}", accountName);
        Optional<Account> accountOptional = getFromDB(accountName);
        if (!accountOptional.isPresent()) {
            throw new IllegalStateException(String.format("can not find account by account name : [%s]", accountName));
        }
        return accountOptional.get();
    }

In this example, there is no more cache evaluation and cache fill logic. All such stuff are taken over by Spring under the hood and completely transparent to application developer, with the help of following bean configuration in xml:

<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean
                    class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
                    <property name="name" value="default" />
                </bean>
                <bean
                    class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
                    <property name="name" value="accountCache" />
                </bean>
            </set>
        </property>
    </bean>

And how to research what magic has been done by Spring to achieve this behavior? We use the following code to research. It is expected that the request sent by line 31 will directly reach database, while the second request in line 34 will be handled by Spring cache handler.

 

 

Here in line 31, in debugger we can find that accountService2 is not an instance of application class com.sap.AccountService2, but a dynamic proxy class generated by Spring.

 

 

As a result after pressing F5, the intercept method of this dynamic proxy class is called:

 

 

In this method, the execution will be delegated to Spring cache handler class:

 

 

In example 1, the logic of cache evaluation and fill is done by application, and now it is done in method execute below.

 

 

First internal cache managed by Spring is checked in line 336 via method findCachedItem. Due to expected cache miss, our application method will be called as usual via reflection, as demonstrated below:

 

 

After application method to retrieve account from database is done, the result, Account instance with id 2495 is filled to Spring cache, the variable contexts below.

 

 

Below is the screenshot for Spring internal cache to store application data, which is based on ConcurrentHashMap. Our cached Account instance with id 2495 could be found there.

 

 

For the second query request issued by application, the cached result will be returned by Spring handler:

 

 

The last question is, how and when the dynamic proxy is generated? Again let’s go to the entry point of Beans initialization:

 

 

Here the dynamic proxy is created based on configuration defined in xml with the help of CGlibAopProxy. For more detail about CGlibAopProxy, please refer to Spring official document.

要获取更多Jerry的原创文章,请关注公众号"汪子熙":

0
1
分享到:
评论

相关推荐

    反射,注解原理和使用的方法

    在Java编程语言中,反射和注解是两个非常重要的特性,它们极大地增强了代码的灵活性和元数据的使用。本文将深入探讨这两个概念的原理及应用方法。 反射(Reflection)是Java提供的一种强大的机制,允许程序在运行时...

    自定义注解案例

    在编译期间,可以使用`@Processor`注解的Java注解处理器进行处理。处理器可以读取并处理源代码中的注解,然后生成新的源代码或资源。这在实现元编程和代码生成时非常有用。 5. **注解的最佳实践**: - 注解应简洁...

    Spring4CachingAnnotationsExample

    在本文中,我们将深入探讨如何使用Spring 4的缓存注解来集成EhCache框架。Spring框架提供了强大的...通过理解这些注解的工作原理以及如何配置和集成EhCache,开发者能够有效地提升应用的性能,减少对后端资源的依赖。

    springcache-1.1.0.zip

    SpringCache是基于注解驱动的,允许开发者通过在方法上添加`@Cacheable`、`@CacheEvict`等注解来启用缓存功能。`@Cacheable`用于缓存方法的返回结果,`@CacheEvict`则用于清除缓存。此外,`@Caching`注解可以用于...

    java 缓存机制

    在Java中,缓存机制可以分为多种实现方式,包括基于注解的声明式缓存和对Cache抽象的理解。 声明式缓存通常通过注解实现,如Spring框架中的`@Cacheable`、`@CacheEvict`等,这些注解使得开发者能够轻松地在方法级别...

    java缓存技术

    Spring通过`@Cacheable`、`@CacheEvict`和`@CachePut`等注解,简化了缓存操作的代码。 - **@Cacheable**:用于标注那些可缓存的方法,当方法被调用时,Spring会检查缓存中是否有对应的键值对,如果有则直接返回,...

    spring缓存实例

    通过学习这个示例,我们可以更直观地理解Spring缓存的工作原理和实际运用。 总的来说,Spring缓存机制极大地提高了应用的响应速度和效率,减少了数据库交互次数。通过合理利用缓存,开发者可以优化系统性能,同时...

    Spring memcached 源码

    Spring Memcached 是一个用于在Spring应用中集成Memcached缓存服务的框架。Memcached是一种分布式内存对象缓存系统,常用于提高网站数据读取...通过源码分析,我们可以了解其工作原理,并根据实际需求进行调整和优化。

    hibernate 注解 英文版的

    在 Hibernate 中,可以使用 XML 文件或注解来定义元数据,而随着 JPA(Java Persistence API)的引入,注解成为一种更加简洁高效的方式。 #### 二、设置注解项目 **2.1 要求** - Java SE 5 或更高版本。 - 支持 ...

    hibernate_cache_level_2.rar_java_staredb4u

    在这个主题下,我们将深入探讨Hibernate的二级缓存机制、其工作原理以及如何在项目中有效实施。 首先,我们来理解什么是Hibernate的二级缓存。一级缓存是每个Session内部的一个缓存,它存储了自Session打开以来所有...

    hibernate二级缓存

    在这个主题中,我们将深入探讨 Hibernate 二级缓存的概念、工作原理以及配置步骤,并通过实例来展示其实际应用。 一、二级缓存概念 在 Hibernate 中,一级缓存是每个 Hibernate 会话内部的私有缓存,负责存储实体...

    hibernate二级缓存示例源码

    本文将深入探讨Hibernate二级缓存的基本概念、工作原理及如何通过示例源码实现。 ### 1. 二级缓存概述 Hibernate的一级缓存是Session级别的,它自动管理对象的状态,提供瞬时、持久化和脱管状态之间的转换。然而,...

    hibernate-annotations-3.4.0.GA.chm中文版

    《Hibernate注解3.4.0.GA中文版》是一个针对Java开发人员的重要参考资料,它详细阐述了如何在Hibernate框架中使用注解进行...同时,了解这些注解背后的原理也有助于理解Hibernate的工作机制,更好地优化应用的性能。

    Hibernate二级缓存实例带jar包

    这个实例提供的jar包应包含了所有必要的依赖,可以直接导入到项目中运行,帮助开发者快速体验和理解二级缓存的工作原理和优势。 二级缓存的使用能显著提升数据库访问效率,降低数据库压力,尤其在数据重复查询频繁...

    更简单的Java缓存框架 jscache.docx

    jscache是一个轻量级、易用的Java缓存框架,它基于面向切面编程(AOP)原理实现,支持灵活配置缓存策略,并提供了多种缓存实现方式。通过使用jscache,开发者能够更加简单高效地管理应用中的缓存数据,提高系统的...

    Hibernate4二级缓存Ehcache案例

    这里的`@Cacheable`注解标记该类为缓存对象,`@Cache`注解定义了缓存的区域和并发策略。 通过以上步骤,我们就成功地在Hibernate4中配置并启用了Ehcache作为二级缓存。在实际应用中,还需要根据业务需求调整缓存...

    事务和缓存(SpringBoot2).rar

    通过运行这个SQL脚本,开发者可以创建一个测试环境,进而实践和理解Seata的工作原理和使用方法。 总的来说,事务和缓存是提升系统性能和保证数据一致性的关键组件。在Spring Boot 2项目中,通过声明式事务管理和...

    java缓存数据

    用户可以通过注解`@Cacheable`、`@CacheEvict`等控制缓存操作,源码中,Spring会根据配置选择合适的缓存管理器进行操作。 2. **工具和框架**: - **Ehcache**:一个广泛使用的开源Java缓存库,支持内存和磁盘存储...

Global site tag (gtag.js) - Google Analytics