【第十一篇】SpringBoot缓存技术

发布于:2025-07-05 ⋅ 阅读:(19) ⋅ 点赞:(0)

简介

        本文全面介绍了Java开发中三种主流的缓存框架技术方案。首先讲解了SpringCache作为声明式缓存抽象层的特点,包括其对Ehcache、Redis等多种缓存实现的支持,重点解析了@Cacheable、@CachePut、@CacheEvict等核心注解的使用方法以及缓存键的组成规则和SpEL表达式应用。其次介绍了阿里开发的JetCache框架,该框架支持本地与远程多级缓存,提供缓存统计、自动刷新等增强功能,并详细说明了@CreateCache和@Cached注解的具体用法及常见问题解决方案。最后阐述了J2Cache框架独特的两级缓存架构设计,该框架基于Ehcache和Redis实现,通过消息机制确保数据一致性,文中还包含了详细的配置说明和问题排查指南。

        文章内容若存在错误或需改进的地方,欢迎大家指正!若对操作有任何疑问欢迎留言!非常感谢!

目录

一、SpringCache 缓存框架

1、导入缓存的坐标

2、开始缓存功能

3、常用注解

4、缓存的键和值

5、使用缓存

二、SpringCache缓存技术

1、切换Ehcache实现

(1)先导入坐标

(2)指定Spring缓存技术为Ehcache

(3)增加Ehcache专用配置文件

(4)补充:淘汰策略

2、切换Redis实现

(1) 引入Redis坐标

(2)指定Spring缓存技术使用Redis

(3)增加Rdis的专用配置

(4)缓存中对Redis的进一步配置

(5)测试

(6)问题排查

3、切换memcached实现

三、JetCache缓存框架

1、问题场景

(1)配置

(2)缓存方式

2、JetCache简介

3、使用JetCache

(1)引入坐标

(2)配置声明缓存模式及技术

(3)启用缓存

(4)使用缓存

第一种:使用缓存空间

第二种:使用注解缓存

(5)刷新缓存

(6)缓存统计

4、JetCache配置示例

5、JetCache使用问题排查

(1)@EnableCreateCacheAnnotation注解提示过时

(2)提示JetCache与Redis版本不兼容问题

(3)启动提示循环依赖,导致启动失败

(4)使用注解设置过期时间不生效

四、J2Cache缓存框架

1、框架简介

(1)简介

(2)核心设计

(3)数据同步机制

2、使用J2Cache

(1)引入坐标

(2)J2Cache配置文件

(3)配置文件相关内容(可跳过)

(4)指定J2Cache的配置文件名称

(5)存取缓存

(6)缓存键的组成

3、J2Cache问题排查

(1)提示Slf4j冲突,控制台报红

(2)提示创建Bean失败


一、SpringCache 缓存框架

        Spring Cache 是 Spring 框架提供的缓存抽象层,它提供了一种声明式的缓存方式,可以轻松地将缓存功能集成到应用程序中,而无需关心底层缓存实现的具体细节。

1、导入缓存的坐标

        Spring Cache的版本由Spring统一管理,引入依赖时无需关心版本。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2、开始缓存功能

        在启动类上面添加@EnableCaching注解即可

3、常用注解

  • @Cacheable:在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,则调用方法并将方法的返回值放到缓存中。
  • @CachePut:将方法的返回值放到缓存中
  • @CacheEvict:删除全部或指定的缓存数据

4、缓存的键和值

        缓存数据一般都是键值对形式,值就是需要缓存的数据,而缓存的键则是通过一定的规则而来的。在@Cacheable和@CachePut注解里有两个属性分别是cacheNames和key,缓存键的组成就是cacheNames的值加两个冒号再加key的值。例如cacheNames的值为users,key的值为1,那么缓存的键就是users::1。其实也可以简单理解cacheNames就是为了做缓存键的前缀。目的是为了防止缓存键重复。

        @Cacheable和@CachePut注解里的value属性和cacheNames属性的效果一样,使用哪个属性都行。一般都会将cacheNames属性或者value属性值设置为业务前缀。

        key值不能写成固定的,若写成了固定的,那么所有的缓存都会使用相同的键,那么后一个的值会将前一个的值覆盖。key值是支持spEL语法的,可以使用‘#变量名’的形式动态获取到方法入参的值。例如getById方法接收一个Integer类型的参数,那么就可以使用‘#id’的形式获取到入参id的值作为key属性值拼接到缓存的键中。

        key的取值所支持的spEL语法的具有多种形式,假如传递的参数是一个对象的话,还可以通过‘.’来获取到指定属性值,‘.’又称为对象导航。

  • 使用对象导航获取到id属性。这样获取到的值是当前方法入参对象里的属性。

  • 使用result加对象导航获取到id属性值。这样获取到的值是当前方法返回值的对象里的属性。

  • 使用p或者a通过索引加对象导航获取到id属性值。不论p或者a都代表当前方法的入参,而后面的数字索引代表方法的第几个入参,从0开始。

  • 使用root获取到入参数组,然后通过索引加对象导航获取到id属性值。root.args[]代表当前方法的入参数组,可以直接通过索引获取到指定的入参,索引从0开始。

5、使用缓存

        当在指定的方法上增加了@Cacheable注解之后,当访问这个方法时,会先查看缓存中是否有对应的数据,若有对应的数据,那么就会直接返回,不再调用原方法;若没有缓存对应的数据,那么就会先调用原方法,然后把原方法的返回值进行缓存起来,最后在进行返回。

        当在指定的方法上增加了@CachePut注解之后,当访问这个方法时,会将这个方法的返回值放入缓存当中,就算之前是存在缓存的,这里会覆盖存入。

        当在指定的方法上增加了@CacheEvict注解之后,当访问这个方法时,会去删除指定键的缓存。

        当在指定的方法上增加了@CacheEvict注解之后,并且指定了allEntries属性为true,那么当访问这个方法时,就会去删除全部的缓存。 

二、SpringCache缓存技术

        SpringBoot提供的缓存技术除了提供的默认缓存方案,还可以对其他缓存技术进行整合,统一了接口,方便缓存技术的开发和管理。如果直接使用SpringCache的话,默认使用的缓存技术是Simple,当然也可以做缓存技术的更换,下面列举的是SpringCache所支持的缓存技术:

  • Generic
  • JCache
  • Ehcache
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple(默认)
  • memcached

下面挑选了几个其他技术进行替换实现。

1、切换Ehcache实现

(1)先导入坐标

        Ehcache的版本由Spring统一管理,引入依赖时无需关心版本。

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
(2)指定Spring缓存技术为Ehcache

        在Spring的配置文件中指定缓存使用的技术为ehcache,默认使用的是simple。

(3)增加Ehcache专用配置文件

        在resources目录下新建一个ehcache.xml文件做为Ehcache的专用配置文件。然后将下面的内容复制粘贴即可,文件里面有详细的注释。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <!--diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。-->
    <diskStore path="E:\ehcache"/>

    <!--name名称是defaultCache是默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。默认缓存策略只能定义一个。-->
    <!--
        缓存策略属性详细解释:
            name:缓存策略的名称。
            eternal:对象是否永久有效,一但设置了,timeout将不起作用。通常设置为false。
            maxElementsInMemory:缓存最大数量
            maxElementsOnDisk:硬盘最大缓存个数。
            overflowToDisk:超过最大缓存数量是否持久化到磁盘
            timeToIdleSeconds:最大闲置时间(单位:秒)。设置过长容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码。
            timeToLiveSeconds:最大存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。
            memoryStoreEvictionPolicy:缓存清除策略。当达到最大缓存数量时,会根据当前策略去清理。默认策略是LRU(最近最少使用)。
   -->
    <defaultCache
            eternal="false"
            diskPersistent="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            timeToIdleSeconds="60"
            timeToLiveSeconds="60"
            memoryStoreEvictionPolicy="LRU"/>
    
</ehcache>

        在Ehcache的专用配置文件中可以配置多个缓存的策略,通过不同的name值进行区分。例如在使用@Cacheable注解指定value或者cacheNames属性值的时候,会自动匹配加载name为相同值的缓存策略配置。

        如果Ehcache的配置文件改名字了,还可以在配置文件中进行指定名称。

(4)补充:淘汰策略

Ehcache缓存数据淘汰策略

  • volatile-lru(默认):挑选最近最少使用的数据淘汰
  • volatile-lfu:挑选最近使用次数最少的数据淘汰
  • volatile-ttl:挑选即将要过期的数据淘汰
  • volatile-random:任意选择数据淘汰

        例如:下面有四个缓存,上面的已经被访问的次数,下面的最后一次访问的时间,那么根据数据淘汰策略,lru淘汰的就是;lfu淘汰的就是。简单来说lru就是长时间不用的淘汰,lfu就是用的最少的淘汰。

2、切换Redis实现

(1) 引入Redis坐标

        Redis的版本由Spring统一管理,引入依赖时无需关心版本。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2)指定Spring缓存技术使用Redis

        在Spring的配置文件中指定缓存使用的技术为redis,默认使用的是simple。

(3)增加Rdis的专用配置

        增加Redis的专用连接配置。

(4)缓存中对Redis的进一步配置

        在Spring中是支持对Redis形式的缓存进行进一步配置的,注意是以spring.cache开头。下面是对配置的详细解释:

  • time-to-live:缓存过期时间,支持Duration类型的时间属性。
  • cache-null-values:是否缓存空值。
  • use-key-prefix:是否使用前缀。默认是true,推荐使用true,因为设置为false的风险太大。若设置成了false,那么不论是@Cacheable或者@CachePut注解中声明的value或Cachenames属性值,还是使用key-prefix指定需要给缓存添加指定的前缀。都将失效!都会变成没有前缀!
  • key-prefix:需要添加的前缀。指定这个之后,再次缓存的时会在@Cacheable或者@CachePut注解中声明的value或Cachenames属性值前面增加这个前缀。

(5)测试

        这里在Controller中写了一个getById方法,然后使用@Cacheablle注解声明了缓存返回值,会将该方法返回的Student对象缓存到Redis中,然后可以看到控制台中只打印了一次日志,然后在Redis中缓存的key就是注解中value的值作为前缀,然后拼接上两个冒号和id的值。然后缓存的值就是getById方法返回的Student对象被序列化后的内容。

(6)问题排查

        若在执行的时候出现了下面的问题:class invalid for deserialization

        原因是因为需要缓存的实体对象没有实现Serializable序列化接口,然后向Redis中序列化的时候出现了问题。只需要将需要被序列化的实体实现Serializable序列化接口即可。

3、切换memcached实现

3.1 安装服务

        只需要将压缩包戒解压到指定位置,然后在当前解压目录下进去CMD窗口,然后执行 exe -d install。注意CMD窗口必须是管理员模式运行,也可以直接管理员运行CMD窗口,然后进入到解压目录,再执行命令。

3.2 启动服务

在解压目录下执行命令

启动命令:exe -d start

停止命令:exe -d stop

3.3 通过客户端使用memcached

Spring Boot未提供对memcached客户端的整合,需要使用硬编码方式实现客户端的初始化管理。

memcached客户端由最早期的客户端,已经被慢慢优化了很多的版本

  • Memcached Client for Java:最早期客户端,稳定可靠,用户群广
  • SpMemcached:效率更高
  • X memcached:并发处理更好

代码实现

3.4 导入坐标

3.5 通过配置类将memcached加载到IOC容器中

因为Spring Boot并未对memcached做整合,所以也没有针对memcached的专用配置,只能通过硬编码配合配置嘞的方式,将memcached的客户端注册到IOC容器当中。

因为我们已经在服务器上将memcached服务启动了,那么就需要在memcached的配置嘞中指定服务的IP和端口。当然MemcachedClient对象有非常多的属性可配置,输入一个set可以看到提示有很多很多的属性,如果有需要可以直接在返回对象之前,进行set即可。

这里直接使用了属性注入为MemcachedClient对象的属性进行赋值。

3.6 使用memcached进行缓存

(1)存入缓存

只需要在当前类中注入MemcachedClient对象,然后调用set方法,可以看到最简单的入参有三个,分别是:缓存的key、过期时间、缓存值

(2)获取缓存

直接使用MemcachedClient对象调用get方法,可以看到需要一个参数,这个参数也就是缓存的key,返回值就是缓存的值

三、JetCache缓存框架

1、问题场景

(1)配置

        通过上面的使用是能发现一些问题的,比如配置太松散,例如Ehcache使用自己的配置文件的,有Redis使用Spring配置文件的,也有memcache直接硬编码的等等,由此可以看出配置太松散,不能统一配置。

(2)缓存方式

        当使用simple和Ehcache进行缓存时是直接用的本地,并没有配置IP和端口。而在使用Redis和memcache时需要配置IP和端口,即远程缓存。这样导致缓存的方式又不一样,如果都使用本地,那么肯定面临分布式部署的服务之间无法共享缓存,若都使用远程,那么又面临网络问题。

2、JetCache简介

        阿里开发了JetCache框架,解决了这些问题。JetCache是对SpringCache进行了封装,在原有功能的基础上实现了多级缓存、缓存统计、自动刷新、异步调用、数据报表等功能。JetCache是一个缓存框架的实现,用于替代SpringCache。

        JetCache设定了本地缓存与远程缓存的多级缓存解决方案,目前仅支持四种缓存技术。

  • 本地缓存(local)
    • LinkedHashMap
    • Caffeine
  • 远程缓存(remote)
    • Redis
    • Tair

3、使用JetCache

(1)引入坐标

        因为JetCache并没有被Spring整合,所以需要到Maven仓库查找到依赖坐标。如果不是Spring的项目那么需要导入的是JetCache Core和JetCache Anno两个坐标,使用的是Spring项目,那么就导入JeiCache Start Redis即可

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.7.8</version>
</dependency>
(2)配置声明缓存模式及技术

        在配置文件中使用JetCache开头的配置,然后再配置远程或者本地缓存模式。远程就用remote,本地就用local,可以只用远程,也可以只用本地,也可以同时使用。

jetcache:
  # 远程缓存
  remote:
    # ... ...
  # 本地缓存
  local:
    # ... ...

        在remote或者local下一级可以配置多组不同的配置,可根据不同的名称进行区分,默认必须有一个default且只能叫default。然后使用type声明要使用的缓存技术。缓存技术就是上面所支持的两种远程和两种本地方式。

jetcache:
  # 远程缓存
  remote:
    # 默认缓存
    default:
      # 声明缓存技术
      type:
  # 本地缓存
  local:
    # 默认缓存
    default:
      # 声明缓存技术
      type:

        注意,在选择Redis作为远程缓存方案的时候,必须要配置poolConfig.maxTotal属性,也就是最大连接数。

jetcache:
  # 远程缓存
  remote:
    # 默认缓存
    default:
      # 声明缓存技术
      type: redis
      host: localhost
      port: 6379
      password: 123456
      poolConfig:
        maxTotal: 50
  # 本地缓存
  local:
    # 默认缓存
    default:
      # 声明缓存技术
      type:

        示例:仅使用远程缓存,缓存技术采用Redis。因采用Redis,所以需要配置最大连接数

jetcache:
  # 远程缓存
  remote:
    # 默认缓存
    default:
      # 声明缓存技术
      type: redis
      host: localhost
      port: 6379
      password: 123456
      poolConfig:
        maxTotal: 50
(3)启用缓存

        需要在启动类上声明@EnableCreateCacheAnnotation注解,声明启用JetCache进行缓存。

(4)使用缓存
第一种:使用缓存空间

        创建缓存空间

        在需要缓存的类中创建一个com.Alice.jetcache包下的Cache接口的对象,相当于是一个缓存空间,Cache接口的对象需要key和value,其实就是缓存空间中缓存的键值对。然后需要在当前对象上声明@CreateCache注解,来声明为缓存的空间。

        注解所需属性

  • area属性:为了声明当前缓存空间使用的是哪组配置,默认值是default。
  • name属性:该属性的作用和@Cacheable和@CachePut中的value或者Cachenames属性的作用是一样的,起到缓存前缀的作用。
  • expire属性:代表当前缓存空间中缓存的过期时间,接收数字参数。
  • tiemUnit属性:时间单位,与expire属性结合使用,默认值为秒。
  • cacheType属性:指定当前缓存空间缓存方式,远程/本地/远程+本地。使用CacheType枚举指定,默认使用远程。

        使用缓存空间

        放入缓存,只需要使用缓存空间对象调用put方法,并传递缓存的键和值;取出缓存,只需要使用缓存空间对象调用get方法,并传递键,然后就能得到指定键的缓存值。

        查看Redis中的缓存。缓存的键的组成:组配置名称+下划线+缓存空间对象上声明的注解的name属性+自己设置的Key。

        值得注意的是,缓存空间对象可以创建任意个,每个缓存空间对象都可以根据注解中的area属性指定相同或者不同的配置,这样可以更加灵活的管理。

        数据不一致性时,可以通过set方法进行规避。

第二种:使用注解缓存

        这种方式可以直接在方法上通过注解的形式将方法的返回值缓存起来,若缓存中有数据,那么就不再调用原方法。与@Cacheable注解的作用相同。

        开启方法注解缓存功能,需要在启动类上添加@EnableMethodCache(basePackages = {"包路径"})注解,然后必须使用basePackages属性指定扫描包路径,可以用字符串指定一个,也可以通过数组指定多个。

        在指定的方法上声明@Cached注解,表示当前方法需要使用缓存,然后注解的属性与缓存空间上声明的@CreateCache注解一样。

        数据不一致性时,可以在update类型的方法上使用@CacheUpdate,修改指定的缓存内容;在delete类型的方法上,使用@CacheInvalidate删除指定的缓存。注解中支持spEL语言。

        使用注解缓存时,缓存的键的默认组成格式是:组配置名称+下划线+缓存空间对象上声明的注解的name属性+[自己设置的Key]。比着空间缓存对象的缓存多了一个中括号。

(5)刷新缓存

        假如有A、B两台服务器,A服务器已经将数据缓存了,然后B服务修改了数据,这样就造成了数据不一致。在JetCache中提供了一个@CacheRefresh注解,注解中有一个refresh属性,这个属性代表多少秒刷新缓存,例如设置为3,那么就代表每3秒就会调用这个方法,并更新缓存。

        不推荐使用,因为这样会对数据库造成压力,不间断查询。

(6)缓存统计

        在配置中jetcache的下一级配置一个statIntervalMinutes属性,接收一个数字。这个属性代表在指定的时间之后(秒)打印缓存命中率等监控数据。如下面的格式,就代表get代表查询次数,hit代表命中缓存次数,例如对同一个id查询7次,因为第一次缓存中没有数据,那么就会查询数据库,那么第一次就没有命中缓存,而剩下的6次因为缓存中已经有了数据,所以直接查询的缓存也就代表命中缓存。fail代表失败次数、expire代表多少过期数据、avgLoadTime代表平均访问时间、maxLoadTime代表最大访问时间。

4、JetCache配置示例

配置解析:

  • areaInCacheName:设置组配置名称是否存入缓存的key,也就是缓存键的组成中的组配置名称。
  • keyConvertor:类型转换,假如key使用的是对象的话,通过这里的指定会将对象转为JSON字符串,这样能够减少底层对比的开销。若存储的key是对象的话,那就需要配置这个参数。
  • limit:缓存数据量
  • valueEncoder:设置存储的值序列化后的数据(实体类实现序列化Serializable接口)
  • valueDecoder:设置存储的值反序列化后的数据(实体类实现序列化Serializable接口)
  • minIdle:最小空闲连接数
  • maxIdle:最大空闲连接数
  • maxTotal:最大连接数
jetcache:
  statIntervalMinutes: 15
  areaInCacheName: false
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
      limit: 100
  remote:
    default:
      host: localhost
      port: 6379
      password: 123456
      type: redis
      keyConvertor: fastjson
      valueEncoder: java
      valueDecoder: java
      poolConfig:
        minIdle: 5
        maxIdle: 20
        maxTotal: 50

5、JetCache使用问题排查

(1)@EnableCreateCacheAnnotation注解提示过时

        在JetCache的2.7.x之后的版本,会提示@EnableCreateCacheAnnotation注解过时,建议使用2.7.x之前的版本,可以将pom文件中JetCache的版本改为2.6.4。

(2)提示JetCache与Redis版本不兼容问题

        提示信息:Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisAutoInit' defined in class path resource [com/alicp/jetcache/autoconfigure/RedisAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/UnifiedJedis

        在我的demo项目中,我并未引入Redis的任何相关依赖,但是底层引入的依赖jedis的版本是3.7.1,那么只需要将底层的进行排除,然后将最新的依赖引入即可。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.4.0</version>
</dependency>
(3)启动提示循环依赖,导致启动失败

        在启动的时候出现如下的情况,是因为产生了循环依赖,第一种解决办法是将jetcache-starter-redis的坐标版本改为2.6.4就可以了。也有在网上说通过配置允许循环依赖就好了,但是个人感觉这样不太妥,因为如果其他地方也有循环依赖的问题,那么就会因为这个配置看不到,可能会有隐藏的问题。

(4)使用注解设置过期时间不生效

        在写demo的时候发现了一个问题,是在使用注解@Cached缓存的时候,发现过期时间不生效,后来发现是在Controller里面缓存空间的内容并没有注释掉,而且缓存空间上使用的@CreateCache注解里的内容与@Cached注解的内容一样,就过期时间不一样,然后过期时间就变成了缓存空间对象设置的过期时间。

        可以看到我在缓存空间的@CreateCache注解里设置的过期时间是6000秒,在注解@Cached缓存的时候设置的过期时间是100秒,最后生效的却是6000秒。而缓存键的组成方式却是注解缓存的格式。

当我将缓存空间对象注释掉之后,发现所有缓存的配置就都以注解缓存的配置为主了。

四、J2Cache缓存框架

1、框架简介

(1)简介

        J2Cache 是一个基于 多级缓存(两级缓存)的高性能分布式缓存框架,主要用于解决高并发场景下的缓存一致性和性能问题。它结合了 本地缓存(L1)分布式缓存(L2),通过 消息通知机制 保证数据一致性,适用于分布式系统。

(2)核心设计

缓存级别

存储位置

特点

适用场景

L1(一级缓存)

应用本地内存(如 Caffeine、Ehcache)

超高速访问(微秒级),但仅限单机

高频读取、低一致性要求的数据

L2(二级缓存)

分布式缓存(如 Redis、Memcached)

跨节点共享,速度较慢(毫秒级)

需要全局一致的数据

(3)数据同步机制
  • 缓存更新:当数据变更时,先更新 L2,再通过 消息队列(如 Redis Pub/Sub、Kafka) 通知其他节点失效本地 L1 缓存。
  • 缓存读取:优先读 L1,未命中时读 L2 并回填到 L1。

2、使用J2Cache

        因为J2Cache是多级缓存框架,所以这里本地缓存使用Ehcache,远程缓存使用Redis,下面的使用将围绕这种形式展开。

(1)引入坐标

        导入J2Cache相关依赖,因为J2Cache并没有被Spring管理,所以需要去Maven仓库中查找并引入。必须指定版本。因为J2Cache也会引入SLF4J的依赖,会出现框架冲突而导致控制台爆红,但是不影响项目的任何问题,所以下面的依赖中排除了SLF4J相关的依赖。

<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-core</artifactId>
    <version>2.8.4-release</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-spring-boot2-starter</artifactId>
    <version>2.8.0-release</version>
</dependency>

        进入到j2cache整合Redis的坐标中可以看到,默认引入了Redis的依赖,因为J2cache建议使用Redis作为缓存的解决方案,所以它默认引入了Redis的坐标,所以可以直接使用Redis。

        如果还想继续使用Ehcache,那么就还需要引入Ehcache的坐标。

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
(2)J2Cache配置文件

        可以在项目的Maven的jar包中找到J2Cache的核心包,然后就可以看到给了一些默认的配置文件,因为当前使用的是J2Cache整合Ehcache和Redis,所以只需要将ehcache.xml和j2cache.properties两个配置文件直接拷贝到项目的resources目录下,然后进行编辑即可。

        ehcache的配置在上面已经有详细说明,下面是一个配置的示例。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <!--diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。-->
    <diskStore path="E:\ehcache"/>

    <!--name名称是defaultCache是默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。默认缓存策略只能定义一个。-->
    <!--
        缓存策略属性详细解释:
            name:缓存策略的名称。
            eternal:对象是否永久有效,一但设置了,timeout将不起作用。通常设置为false。
            maxElementsInMemory:缓存最大数量
            maxElementsOnDisk:硬盘最大缓存个数。
            overflowToDisk:超过最大缓存数量是否持久化到磁盘
            timeToIdleSeconds:最大闲置时间(单位:秒)。设置过长容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码。
            timeToLiveSeconds:最大存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。
            memoryStoreEvictionPolicy:缓存清除策略。当达到最大缓存数量时,会根据当前策略去清理。默认策略是LRU(最近最少使用)。
   -->
    <defaultCache
            eternal="false"
            diskPersistent="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            timeToIdleSeconds="60"
            timeToLiveSeconds="60"
            memoryStoreEvictionPolicy="LRU"/>
    
</ehcache>

        因为J2Cache是多级缓存框架,所以需要在配置文件中配置一级缓存和二级缓存,以及一级缓存如何到达二级缓存。J2Cache的配置文件中是支持很多很多的配置的,具体详情可自行了解。

# 1级缓存
j2cache.L1.provider_class = ehcache
ehcache.configXml = ehcache.xml

# 2级缓存
j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.config_section = redis
redis.hosts = 127.0.0.1:6379
redis.password = 123456

# 1级缓存中的数据如何到达二级缓存
j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
(3)配置文件相关内容(可跳过)

        下面是J2Cache的配置文件扩展内容,通过第二节中的配置文件已经可以正常使用,如需要扩展再使用。

        是否启用二级缓存,这个是属于J2Cache的配置,默认为true,若配置成了false,那么就只使用Ehcache进行缓存,不再缓存到Redis中。

        redis模式的配置

        redis缓存前缀,默认为空,如果在这配置了redis.namespace的值的话,那么所有通过J2Cache到达Redis的缓存都会加上这个前缀和一个冒号。可以看一下下面第六小节中键的组成,除了在代码里面设置的前缀之外,还可以在这设置统一的前缀。

        redis连接相关配置

        redis连接池相关配置

(4)指定J2Cache的配置文件名称

        在application.yaml配置文件中通过配置j2cache.config-location来指定J2Cache的配置文件,J2Cache的具体配置就在这个配置文件中。

j2cache:
  config-location: j2cache.properties # 指定配置文件路径
  # config-location: classpath:j2cache.properties # 加不加classpath:都行
(5)存取缓存

        首先需要在需要的地方注入缓存类CacheChannel的对象,然后取缓存只需要调用get方法并传递两个参数,分别是缓存键的前缀和自定义key即可,取出的是CacheObject类型的对象,这个对象的value属性就是缓存的内容,默认是一个Object类型。存缓存只需要调用set方法并传递三个参数,分别是缓存的前缀、自定义key、需缓存的数据。

        启动项目,控制台出现下面的信息代表配置成功,即可正常使用

        可以看到有很多重载的set方法,可根据需求传不同的参数。

(6)缓存键的组成

        使用J2Cache的CacheChannel对象的set方法,在Redis中形成的键就是 第一个region参数值+冒号+自定义key。第一个参数值可以理解为缓存前缀,自定义key是为了防止缓存冲突。

3、J2Cache问题排查

(1)提示Slf4j冲突,控制台报红

        在引入J2Cache的坐标之后,启动项目,控制台出现下面的爆红。这是因为发生了SLF4J框架冲突,Spring默认是会引入SLF4J的,在J2Cache中也有引用,造成了冲突,虽然这里控制台爆红,但是不影响项目的任何使用。解决办法就是在引入J2Cache的坐标的时候把SLF4J相关的依赖排除即可。

<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-core</artifactId>
    <version>2.8.4-release</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </exclusion>
    </exclusions>
</dependency>
(2)提示创建Bean失败

        在运行项目的时候,一直提示BeanCreationException,提示的信息中说redis连接失败,最终排查到问题是在j2cache.properties的配置文件里面配置redis的IP和端口的问题,只能使用 redis.hosts = IP:端口 而我是使用了redis.host = IP redis.port = 端口,两个配置,导致一直连接Redis失败,而提示创建Bean失败。

        错误信息

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2025-07-03 14:30:25.973 ERROR 18916 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentServiceImpl': Unsatisfied dependency expressed through field 'cacheChanneL'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheChannel' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [net.oschina.j2cache.CacheChannel]: Factory method 'cacheChannel' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'j2CacheRedisTemplate' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'j2CacheRedisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'j2CahceRedisConnectionFactory' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:332) ~[spring-context-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.23.jar:5.3.23]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.23.jar:5.3.23]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.13.jar:2.6.13]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745) [spring-boot-2.6.13.jar:2.6.13]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420) [spring-boot-2.6.13.jar:2.6.13]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-2.6.13.jar:2.6.13]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317) [spring-boot-2.6.13.jar:2.6.13]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.6.13.jar:2.6.13]
	at com.xbb.SpringbootDemo14Application.main(SpringbootDemo14Application.java:10) [classes/:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentServiceImpl': Unsatisfied dependency expressed through field 'cacheChanneL'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheChannel' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [net.oschina.j2cache.CacheChannel]: Factory method 'cacheChannel' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'j2CacheRedisTemplate' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'j2CacheRedisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'j2CahceRedisConnectionFactory' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:479) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:550) ~[spring-context-5.3.23.jar:5.3.23]
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:520) ~[spring-context-5.3.23.jar:5.3.23]
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:673) ~[spring-context-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:228) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:329) ~[spring-context-5.3.23.jar:5.3.23]
	... 17 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheChannel' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [net.oschina.j2cache.CacheChannel]: Factory method 'cacheChannel' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'j2CacheRedisTemplate' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'j2CacheRedisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'j2CahceRedisConnectionFactory' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.23.jar:5.3.23]
	... 34 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [net.oschina.j2cache.CacheChannel]: Factory method 'cacheChannel' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'j2CacheRedisTemplate' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'j2CacheRedisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'j2CahceRedisConnectionFactory' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.23.jar:5.3.23]
	... 47 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'j2CacheRedisTemplate' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'j2CacheRedisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'j2CahceRedisConnectionFactory' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1160) ~[spring-context-5.3.23.jar:5.3.23]
	at net.oschina.j2cache.cache.support.util.SpringUtil.getBean(SpringUtil.java:36) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at net.oschina.j2cache.cache.support.redis.SpringRedisProvider.start(SpringRedisProvider.java:87) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at net.oschina.j2cache.CacheProviderHolder.init(CacheProviderHolder.java:69) ~[j2cache-core-2.8.4-release.jar:na]
	at net.oschina.j2cache.J2CacheBuilder.initFromConfig(J2CacheBuilder.java:110) ~[j2cache-core-2.8.4-release.jar:na]
	at net.oschina.j2cache.J2CacheBuilder.getChannel(J2CacheBuilder.java:65) ~[j2cache-core-2.8.4-release.jar:na]
	at net.oschina.j2cache.autoconfigure.J2CacheAutoConfiguration.cacheChannel(J2CacheAutoConfiguration.java:43) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at net.oschina.j2cache.autoconfigure.J2CacheAutoConfiguration$$EnhancerBySpringCGLIB$$f1e5a73b.CGLIB$cacheChannel$0(<generated>) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at net.oschina.j2cache.autoconfigure.J2CacheAutoConfiguration$$EnhancerBySpringCGLIB$$f1e5a73b$$FastClassBySpringCGLIB$$29c4a555.invoke(<generated>) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.23.jar:5.3.23]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.23.jar:5.3.23]
	at net.oschina.j2cache.autoconfigure.J2CacheAutoConfiguration$$EnhancerBySpringCGLIB$$f1e5a73b.cacheChannel(<generated>) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_301]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_301]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_301]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_301]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.23.jar:5.3.23]
	... 48 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'j2CahceRedisConnectionFactory' defined in class path resource [net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.23.jar:5.3.23]
	... 74 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.IllegalArgumentException
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.23.jar:5.3.23]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.23.jar:5.3.23]
	... 88 common frames omitted
Caused by: java.lang.IllegalArgumentException: null
	at net.oschina.j2cache.autoconfigure.J2CacheSpringRedisAutoConfiguration.jedisConnectionFactory(J2CacheSpringRedisAutoConfiguration.java:90) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at net.oschina.j2cache.autoconfigure.J2CacheSpringRedisAutoConfiguration$$EnhancerBySpringCGLIB$$8b913113.CGLIB$jedisConnectionFactory$1(<generated>) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at net.oschina.j2cache.autoconfigure.J2CacheSpringRedisAutoConfiguration$$EnhancerBySpringCGLIB$$8b913113$$FastClassBySpringCGLIB$$cf6c677f.invoke(<generated>) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.23.jar:5.3.23]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.23.jar:5.3.23]
	at net.oschina.j2cache.autoconfigure.J2CacheSpringRedisAutoConfiguration$$EnhancerBySpringCGLIB$$8b913113.jedisConnectionFactory(<generated>) ~[j2cache-spring-boot2-starter-2.8.0-release.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_301]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_301]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_301]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_301]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.23.jar:5.3.23]
	... 89 common frames omitted

        错误示范

        正确配置