<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBootCache源碼解析:Cache自動(dòng)配置

          共 7238字,需瀏覽 15分鐘

           ·

          2022-04-25 07:52


          SpringBootCache源碼解析

          Spring Boot 支持了多種緩存的自動(dòng)配置,其中包括 Generic、JCache、EhCache 2.x、Hazelcast、 Infinispan、 Couchbase、 Redis 、Caffeine 和 Simple。早期版本還支持Guava 的緩存,但目前已經(jīng)廢棄。本章將重點(diǎn)講解緩存的自動(dòng)配置 CacheAutoConfiguration和默認(rèn)的 SimpleCacheConfiguration 自動(dòng)配置及相關(guān)內(nèi)容。


          Cache 簡介

          隨著項(xiàng)目的發(fā)展,往往會(huì)出現(xiàn)- -些瓶頸, 比如與數(shù)據(jù)庫的交互、與遠(yuǎn)程服務(wù)器的交互等。

          此時(shí),緩存便派上了用場。而在 Spring 3.1 中引入了基于注解的 Cache 的支持在spring-context 包 中 定 義 了
          org.springframework.cache. CacheManager 和org.springframework.cache.Cache 接口,用來統(tǒng)一-不同的緩存的技術(shù)。

          CacheManager 是 Spring 提供的各種緩存技術(shù)管理的抽象接口,而 Cache 接口包含緩存的增加、刪除、讀取等常用操作。針對(duì) CacheManager, Spring 又提供了多種實(shí)現(xiàn),比如基于Collection 來 實(shí) 現(xiàn) 的 SimpleCacheManager 、 基 于 ConcurrentHashMap 實(shí) 現(xiàn) 的
          Concurrent-MapCacheManager、基于 EhCache 實(shí)現(xiàn)的 EhCacheCacheManager 和基于JCache 標(biāo)準(zhǔn)實(shí)現(xiàn)的 JCacheCacheManager 等。

          Spring Cache 的實(shí)現(xiàn)與 Spring 事務(wù)管理類似,都是基于 AOP 的方式。其核心思想是:第一次調(diào)用緩存方法時(shí),會(huì)把該方法參數(shù)和返回結(jié)果作為鍵值存放在緩存中,當(dāng)同樣的參數(shù)再次請(qǐng)求方法時(shí)不再執(zhí)行該方法內(nèi)部業(yè)務(wù)邏輯,而是直接從緩存中獲取結(jié)果并返回。

          Spring Cache 提供了@CacheConfig、@Cacheable 、@CachePut 、@CacheEvict 等注解來完成緩存的透明化操作,相關(guān)功能如下。.@CacheConfig:用于類上,緩存一些公共設(shè)置。

          .@Cacheable:用于方法上,根據(jù)方法的請(qǐng)求參數(shù)對(duì)結(jié)果進(jìn)行緩存,下次讀取時(shí)直接讀取緩存內(nèi)容。

          .@CachePut: 用于方法上,能夠根據(jù)方法的請(qǐng)求參數(shù)對(duì)其結(jié)果進(jìn)行緩存,和@Cacheable不同的是,它每次都會(huì)觸發(fā)真實(shí)方法的調(diào)用。

          .@CacheEvict: 用于方法上,清除該方法的緩存,用在類上清除整個(gè)類的方法的緩存。

          在了解了 Spring Cache 的基本作用的和定義之后,下面來看在 SpringBoot 中是如何對(duì)Cache 進(jìn)行自動(dòng)配置的。


          Cache 自動(dòng)配置

          在 Spring Boot 中,關(guān)于 Cache 的默認(rèn)自動(dòng)配置類只有 CacheAutoConfiguration,主要用于緩存抽象的自動(dòng)配置,當(dāng)通過@EnableCaching 啟用緩存機(jī)制時(shí),根據(jù)情況可創(chuàng)建CacheManager。對(duì)于緩存存儲(chǔ)可以通過配置自動(dòng)檢測或明確指定。

          CacheAutoConfiguration 同樣在 ME TA-INF/spring.factories 文件中配置注冊(cè)。

          # . Auto Configure
          org. springframework. boot. autoconfigure . EnableAutoConfiguration=\
          org. springframework . boot . autoconfigure . cache . CacheAutoConfiguration, \
          下面先來看 CacheAutoConfiguration 類的注解部分代碼實(shí)現(xiàn)。
          @Configuration(proxyBeanMethods = false)
          @ConditionalOnClass (CacheManager. class)
          @ConditionalOnBeanCacheAspectSupport . class)
          @ConditionalOnMissingBean(value = CacheManager .class, name = "cacheResolve
          r"
          )
          @EnableConfigurationProperties (CacheProperties. class)
          @AutoConfigureAfter({ CouchbaseAutoConfiguration. class, HazelcastAutoConfig
          uration. class,
          HibernateJpaAutoConfiguration. class, RedisAutoConfigur
          ation.class })
          @Import(CacheConfigurat ionImportSelector.class)
          public class CacheAutoConfiguration {
          }

          @ConditionalOnClass 指 定 需 要 在 classpath 下 存 在 CacheManager 類 。關(guān) 于CacheManager 類是一個(gè)緩存管理器的接口,管理各種緩存(Cache) 組件。針對(duì)不同的緩存技術(shù),會(huì)有不同的實(shí)現(xiàn)類。比如,在 Spring 中提供了 SimpleCacheManager (測試)、
          Concurrent-MapCacheManager ( 默 認(rèn) ) 、 NoOpCacheManager ( 測 試 ) 、EhCacheCacheManager ( 基于 EhCache)、RedisCacheManager (基于 Redis) 等實(shí)現(xiàn)類。CacheManager 接口提供了兩個(gè)方法:根據(jù)名稱獲取緩存和獲取緩存名稱集合,相關(guān)代碼如下。

          public interface CacheManager {
          //根據(jù)名稱獲取緩存
          @Nullable
          Cache getCache(String name);
          //獲取緩存名稱集合
          Collection getCacheNames();
          }

          在 CacheManager 接 口 中 只 定 義 了 上 面 兩 個(gè) 方 法 , 但 在 其 抽 象 實(shí) 現(xiàn) 類AbstractCache-Manager 中便擴(kuò)展了新增 Cache、更新 Cache 等方法。

          @ConditionalOnBean 指定需要存在 CacheAspectSupport 的 Bean 時(shí)才生效,換句話說,就 是 需要在使用 了 @EnableCaching 時(shí) 才 有 效 。這 是 因 為 該 注 解 隱 式 的 導(dǎo) 致 了CacheInter-ceptor 對(duì)應(yīng)的 Bean 的初始化,而 CacheInterceptor 為 CacheAspectSupport的子類。

          @ConditionalOnMissingBean 指定名稱為 cacheResolver 的 CacheManager 對(duì)象不存在時(shí)生效。

          @
          EnableConfigurationProperties 加 載 緩 存 的 CacheProperties 配 置 項(xiàng) , 配 置 前 綴 為spring.cache.

          @AutoConfigureAfter 指定該自動(dòng)配置必須在緩存數(shù)據(jù)基礎(chǔ)組件自動(dòng)配置之后進(jìn)行,這里包括 Couchbase、 Hazelcast、 HibernateJpa 和 Redis 的自動(dòng)配置

          想要實(shí)現(xiàn)緩存,需要先集成對(duì)應(yīng)的緩存框架或組件。這里以 Redis 為例,它的自動(dòng)配置類RedisAutoConfiguration 中 便 完 成 了 Redis 相 關(guān) 的 Redis Template 和 StringRedisTemplate 的實(shí)例化。而 RedisAutoConfiguration 中導(dǎo)入類
          JedisConnectionConfiguration又完成了 Redis 使用 Jedis 連接的配置

          @Ilmport 導(dǎo)入
          CacheConfigurationlmportSelector,其實(shí)是導(dǎo)入符合條件的 Spring Cache 使用的各類基礎(chǔ)緩存框架(或組件)的配置。該類的實(shí)現(xiàn)就位于 CacheAutoConfiguration 中,代碼如下。

          static class CacheConfigurat ionImportSelector implements ImportSelector {
          public String[] selectImports(Annotat ionMetadata importingClassMetadata)
          CacheType[] types = CacheType.values();
          for(inti=0:i1t+)5
          imports[i] = CacheConfigurations . getConfigurat ionClass(types[i]);
          return imports; }
          }

          導(dǎo)入類的獲取是通過實(shí)現(xiàn) ImportSelector 接口來完成的,具體獲取步驟位于 selectlmports方法中。該方法中,首先獲取枚舉類 CacheType 中定義的緩存類型數(shù)據(jù),CacheType 中定義支 持的緩存類型如下。

          //支持的緩存類型(按照優(yōu)先級(jí)定義)
          public enum CacheType {
          //使用上下文中的 Cache Bean 進(jìn)行通用緩存
          GENERIC,
          // JCache(JSR- 107) 支持的緩存
          JCACHE,
          // EhCache 支持的緩存
          EHCACHE,
          // Hazelcast 支持的緩存
          HAZELCAST,
          // Infinispan 支持的緩存
          INFINISPAN,
          // Couchbase. 支持的緩存
          COUCHBASE,
          // Redis.支持的緩存
          REDIS,
          // Caffeine 支持的緩存
          CAFFEINE,
          //內(nèi)存基本的簡單緩存
          SIMPLE,
          // 不支持緩存
          NONE
          }

          枚舉類 CacheType 中定義了以上支持的緩存類型,而且上面的緩存類型默認(rèn)是按照優(yōu)先級(jí)從前到后的順序排列的。

          selectlmports 方法中,當(dāng)獲取 Cache Type 中定義的緩存類型數(shù)組之后,遍歷該數(shù)組并通過CacheConfigurations 的 getConfigurationClass 方法獲得每種類型緩存對(duì)應(yīng)的自動(dòng)配置類( 注解@Configuration 的類)。

          CacheConfigurations 相關(guān)代碼如下。

          final class CacheConfigurations {
          private static final Map> MAPPINGS;
          //定義 CacheType 5@Conf iguration 之間的對(duì)應(yīng)關(guān)系
          static {
          Map> mappings = new EnumMap<>(CacheType.class);
          mappings . put(CacheType . GENERIC, GenericCacheConfiguration.class);mappings . put(CacheType . EHCACHEEhCacheCacheConfiguration. class);
          mappings . put (CacheType . HAZELCAST, HazelcastCacheConfiguration. class);
          mappings . put(CacheType . INF INISPAN, InfinispanCacheConfiguration.class);
          mappings . put (CacheType . JCACHE, JCacheCacheConfiguration. class);
          mappings . put (CacheType . COUCHBASE, CouchbaseCacheConfiguration. class);
          mappings . put (CacheType. REDIS, RedisCacheConfiguration.class);
          mappings . put(CacheType . CAFFEINE, CaffeineCacheConfiguration. class);
          mappings . put(CacheType . SIMPLE, SimpleCacheConfiguration.class);
          mappings . put(CacheType . NONE, NoOpCacheConfiguration.class);
          MAPPINGS = Collections . unmodifiableMap(mappings);
          //根據(jù) CacheType
          型獲得對(duì)應(yīng)的@Configuration 類
          static String getConfigurationClass(CacheType cacheType) {
          Class configurationClass = MAPPINGS . get(cacheType);
          Assert.state(configurationClass != null, () -> "Unknown cache type ”+
          cacheType) ;
          return configurationClass . getName();
          }
          }

          經(jīng)過以上步驟,我們會(huì)發(fā)現(xiàn)通過@Import 注解,CacheAutoConfiguration 導(dǎo)入了 CacheType中定義的所有類型的自動(dòng)配置,也就是 Spring Boot 目前支持的緩存類型。而具體會(huì)自動(dòng)配置哪種類型的緩存,還需要看導(dǎo)入的自動(dòng)配置類里面的生效條件。

          我們以 GenericCacheConfiguration 為例進(jìn)行了解,源代碼如下。

          @Configurat ion(proxyBeanMethods = false)
          @ConditionalOnBean(Cache . class)
          @ConditionalOnMissingBean(CacheManager . class)
          @Conditional(CacheCondition. class)
          class GenericCacheConfiguration {
          @Bean
          SimpleCacheManager cacheManager(CacheManagerCustomizers customizers, Coll
          ection
          caches) {
          SimpleCacheManager cacheManager = new SimpleCacheManager();
          cacheManager . setCaches(caches);
          return customizers . customize(cacheManager);
          }}

          在 GenericCacheConfiguration 的注解部分,@ConditionalOnBean 指定當(dāng) Cache 的 Bean存在時(shí)進(jìn)行實(shí)例化操作,@ConditionalOnMissingBean 指定當(dāng) CacheManager 的 Bean 不存在時(shí)進(jìn)行實(shí)例化操作,@Conditional 指定當(dāng)滿足 CacheCondition 指定的條件時(shí)進(jìn)行實(shí)例化操作。

          CacheManager 我們前面已經(jīng)介紹過,不再贅述。Cache 是一 個(gè)定義了緩存通用操作的接口,其中定義了緩存名稱獲取、緩存值獲取、清除緩存、添加緩存值等操作。對(duì)應(yīng)的緩存組件或框架實(shí)現(xiàn)該接口,并根據(jù)組件自身的情況提供對(duì)應(yīng)的操作方法實(shí)現(xiàn)。

          下面看 CacheCondition 類中定義的條件。

          class CacheCondition extends SpringBootCondition {
          @Override
          public ConditionOutcome getMatchOutcome (ConditionContext context, Annot
          ated-
          TypeMetadata metadata) {
          String sourceClass =
          if (metadata instanceof ClassMetadata) {
          sourceClass = ((ClassMetadata) metadata). getClassName() ;
          Condit ionMessage . Builder message = ConditionMessage . forCondition("C
          ache"
          ,
          sourceClass);
          Environment environment = context . getEnvironment( ) ;
          try {
          //創(chuàng)建指定環(huán)境的 Binder, 然后綁定屬性到對(duì)象上
          BindResult<CacheType> specified = Binder . get( environment) . bind
          ("spring.
          cache. type"
          , CacheType . class);
          //如果未綁定,則返回匹配
          if (!specified. isBound())
          {
          return ConditionOutcome . match(message . because("automatic ca
          che type"
          ));
          //獲取所需的緩存類型
          CacheType required = CacheConfigurations . getType(((AnnotationMe
          tadata)
          metadata) . getClassName());
          //如果已綁定,并且綁定的類型與所需的緩存類型相同,則返回匹配
          if (specified.get() == required) {return Conditi onOutcome . match(message. because(specified. get
          () +”cache type"));
          } catch (BindException ex) {
          //其他情況則返回不匹配
          return ConditionOutcome . noMatch(message . because("
          unknown cache typ
          e"));
          }
          }

          CacheCondition 的核心邏輯就是首先通過 Binder 進(jìn)行指定屬性和類的綁定,然后通過綁定結(jié)果( BindResult)進(jìn)行判斷:如果判斷結(jié)果是未綁定,則直接返回條件匹配;否則,判斷綁定的緩存類型與所需的緩存類型是否相等,如果相等則返回條件匹配;其他情況則返回條件不匹配。

          當(dāng) GenericCacheConfiguration 滿足注解指定的條件后,便會(huì)通過 cacheManager 方法進(jìn)行SimpleCacheManager 類的實(shí)例化操作。首先創(chuàng)建 SimpleCacheManager 對(duì)象,然后將緩存 集 合 設(shè) 置 到 對(duì) 象 中 , 最 后 通 過 CacheManagerCustomizers 的 customize 方 法 對(duì)SimpleCacheManager 進(jìn)行定制化處理。

          SimpleCacheManager 類是接口 CacheManager 的一個(gè)實(shí)現(xiàn)類,通過集合來實(shí)現(xiàn)緩存功能,源代碼如下。

          public class SimpleCacheManager extends AbstractCacheManager {
          private Collection caches = Collections . emptySet();
          //設(shè)置緩存集合
          public void setCaches (Collection caches) {
          this.caches = caches;
          //獲取緩存集合
          @Override
          protected Collection loadCaches() {
          return this. caches;
          }
          }

          通過以上代碼可以看出,SimpleCacheManager 的實(shí)現(xiàn)極其簡單, 就是基于 Cache 的集合來實(shí)現(xiàn)的,它提供了設(shè)置緩存集合和獲取緩存集合的方法。同樣,由于實(shí)現(xiàn)比較簡單,它往往被用于測試環(huán)境和簡單緩存場景中。

          上面我們以 GenericCacheConfiguration 為例講解了@Import 引入的緩存組件配置,關(guān)于其他的類型緩存注解的配置就不再一-講解了。

          下 我 繼 看 @Ilmport 的
          CacheManagerEntityManagerFactoryDependsOnPostProcess-or類。該類同樣為 CacheAutoConfiguration 的內(nèi)部類。

          @ConditionalOnClass(LocalContainerEnt ityManagerFactoryBean. class)
          @Conditiona lOnBean(AbstractEntityManagerFactoryBean.class)
          static class CacheManagerEntityManagerFactoryDependsOnPostProcessor
          extends EntityManagerFactoryDependsOnPostProcessor {
          CacheManagerEntityManagerFactoryDependsOnPostProcessor() {
          super("cacheManager");}
          }

          該 類 實(shí) 現(xiàn) 了
          EntityManagerFactoryDependsOnPostProcessor, 本質(zhì)上是BeanFactoryPost-Processor 的 一 個(gè) 實(shí) 現(xiàn) 類 。當(dāng) classpath中存在LocalContainerEntityManagerFactoryBean類和實(shí)現(xiàn)了抽象類AbstractEntityManagerFactoryBean 的類的 Bean 時(shí),才會(huì)進(jìn)行實(shí)例化操作。

          在該類的構(gòu)造方法中調(diào)用父類構(gòu)造方法并傳遞值"cacheManager”。因此,動(dòng)態(tài)聲明了所有類型為 EntityManagerFactory 的 Bean 都必須依賴于名稱為 cacheManager 的 Bean。


          最后,我們看一下 CacheAutoConfiguration 中其余的代碼。

          //實(shí)例化 CacheManagerCus tomizers
          @Bean
          @ConditionalOnMissingBean
          public CacheManagerCustomizers cacheManagerCustomizers(
          ObjectProvider> customizers) {
          return new CacheManagerCustomizers(
          customi zers . orderedStream(). collect(Collectors . toList()));
          }

          cacheManagerCustomizers 方法初始化了 CacheManagerCustomizers 對(duì)象的 Bean,主要是 將 容 器 中 存 在 的 一 一 個(gè) 或 多 個(gè) CacheManagerCustomizer 的 Bean 組 件 包 裝 為CacheManager-Customizers,并將 Bean 注入容器。

          //實(shí)例化 CacheManagerVal idator
          @Bean
          public CacheManagerValidator cacheAutoConfigurat ionValidator(CachePropert
          ies-
          cachePropert
          ies,
          objectProvid
          er cacheManager) {
          return new CacheManagerValidator(cacheProperties, cacheManager);
          // CacheManagerVal idator 的具體定義,用于檢查并拋出有意義的異常 static class
          CacheManagerValidator implements InitializingBean {private final CacheProperties cacheProperties;
          private final objectProvider cacheManager;
          CacheManagerValidator(CacheProperties cacheProperties, objectProviderkCac
          he-
          Manager> cacheManager) {
          this. cacheProperties = cacheProperties;
          this. cacheManager = cacheManager;
          }
          @Override
          public void afterPropertiesSet() {
          Assert . notNull(this . cacheManager . getIfAvailable(),
          ) -> "No cache manager could be auto- configured, check
          your configuration (caching ”+ "
          type is” + this. cacheProperties .getType
          () + "')");
          }
          }


          cacheAutoConfigurationValidator 方法初始化了 CacheManagerValidator 的 Bean,該 Bean用于確保容器中存在一個(gè) CacheManager 對(duì)象, 以達(dá)到緩存機(jī)制可以繼續(xù)被配置和使用的目的,同時(shí)該 Bean 也用來提供有意義的異常聲明。

          至此關(guān)于 Spring Boot 中 cache 的 CacheAutoConfiguration 自動(dòng)配置講解完畢,隨后我們會(huì)繼續(xù)講一下Spring Boot 中默認(rèn)的自動(dòng)配置。

          本文給大家講解的內(nèi)容是SpringBootCache源碼解析:Cache自動(dòng)配置

          1. 下篇文章給大家講解的是SpringBootCache源碼解析:默認(rèn)Cache配置;

          2. 覺得文章不錯(cuò)的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;

          3. 感謝大家的支持!

          本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號(hào)里找我,我等你哦。


          瀏覽 31
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费费国产黄色影院 | 99久久久无码国产精品性波多 | 国产女人18毛片精品18水 | 久福利| 亚洲无码18禁 |