首页 > 数据库 >springboot中解决redissonClien无法注入,封装工具雷

springboot中解决redissonClien无法注入,封装工具雷

时间:2023-07-16 10:44:25浏览次数:48  
标签:ApplicationContext redissonClien 封装 springboot -- 博客 RedissonClient import publi

引用:https://blog.csdn.net/feiying0canglang/article/details/120464693

问题来源

前几天遇到一个循环依赖问题,是RedissonClient这个bean引起的。RedissonClient是由一个配置类(@Configuration注解的类)提供的,这配置类在初始化时(@PostConstruct注解的方法中)去获取RedissonClient这个bean。我在自动注入(@Autowired)RedissonClient时发现报循环依赖异常,应用无法启动。

为什么配置类要在实例化时获取自己管理的bean呢?因为代码的作者是要把这个配置类作为工具类,这个工具类要用到这个bean。这个工具类是作为Redis分布式锁用的,用到RedissonClient锁相关方法,而我想注入RedissonClient,使用它读写Redis的方法。

本文介绍这个问题是如何引起的,以及如何解决。

题外话

刚遇到这个问题时,我其实有点窃喜的。原因是:这个问题我知道快速解决的方案,也想通过这个问题来深入了解循环依赖的原理。

快速解决的方案是:不进行自动注入,使用时再使用ApplicationContext来获取,对应这篇博客:Spring--ApplicationContext--使用/教程/原理_IT利刃出鞘的博客-CSDN博客

我之前写过关于循环依赖的博客,对循环依赖也算是比较熟悉了,我感觉我能以比较优雅的方式来解决这个问题。循环依赖相关博客为:

Spring--循环依赖--解决方案--实例_IT利刃出鞘的博客-CSDN博客_IT利刃出鞘的博客-CSDN博客
Spring--原理--循环依赖--@Autowired_IT利刃出鞘的博客-CSDN博客

这也说明了写博客的重要性,有问题直接找就行,自己实测过的代码,用起来绝对放心。
————————————————
版权声明:本文为CSDN博主「IT利刃出鞘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/feiying0canglang/article/details/120464693

本处为了简单起见不引用RedisClient依赖,自己写一个简单的类进行示例。

方案1:不自动注入
SpringBoot启动时会扫描所有被@Component注解的bean,然后去扫描这个bean里边的字段,如果它有@Autowired注解,那就从Spring容器中找它然后将引用地址赋值给这个字段,如果找不到则去实例化它。

本文的使用@Autowired注入RedissonClient就是这样,启动时去实例化它导致的失败。

所以思路很简单,我不自动注入,我使用的时候再获取,这样启动时就不会去实例化它。获取的方法为:使用ApplicationContext。想详细了解ApplicationContext的可以见此文。
————————————————
版权声明:本文为CSDN博主「IT利刃出鞘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/feiying0canglang/article/details/120464693

方案2:延迟注入

        Spring有延迟注入的方法,使用的时候再去实例化这个bean,而不是启动时就实例化,见这里:Spring(SpringBoot)--延迟加载(@Lazy注解等)--使用/原理_IT利刃出鞘的博客-CSDN博客_service 延迟加载

方案3:用方法获得bean

此方法更简单了,对代码的改动最小。

方案4:bean放到外部管理
对于这个RedisLockUtil配置类,它同时也是工具类,它用到了RedissonClient的锁功能,其实RedissonClient的其他读写Redis的方法也巨好用,就像操作JDK中的List、Set、Map一样,RedissonClient实际是实现了JDK中的List、Set、Map,所以使用RedissonClient操作Redis就像我们操作JDK的List、Set、Map一样,超级便利。基于此,我把RedissonClient的配置单独拿出来。
————————————————
版权声明:本文为CSDN博主「IT利刃出鞘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/feiying0canglang/article/details/120464693

方案5:工具类不加入容器(推荐)

        思考一下:RedisLockUtil是个工具类,我们想用的是它的静态方法,所以,最好不将其加入容器。本方案为最优方案,个人感觉是最优雅的方案。

工具类

package com.example.util;
 
import com.example.entity.RedissonClient;
 
public class RedisLockUtil {
    private static RedissonClient redissonClient;
    private static final String PREFIX = "rbac:user:" ;
 
    static {
        System.out.println("RedisLockUtil.static initializer");
        RedisLockUtil.redissonClient = ApplicationContextHolder.getContext().getBean(RedissonClient.class);
    }
 
    public static void lock(String name) {
        RedisLockUtil.redissonClient.getLock(PREFIX + name);
    }
}

  RedissonClient

package com.example.entity;
 
public class RedissonClient {
    public void getLock(String string) {
        System.out.println("RedissonClient#getLock:" + string);
    }
 
    public void getMap() {
        System.out.println("RedissonClient#getMap");
    }
}

  Redisson配置类

package com.example.config;
 
import com.example.entity.RedissonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 

@Configuration
public class RedissonConfig {
	@Value("${spring.redis.host}")
	private String host;
	@Value("${spring.redis.port}")
	private String port;
	@Value("${spring.redis.password}")
	private String password;

	@Bean
	public RedissonClient getRedisson() {
        Config config = new Config();
        SingleServerConfig singleServerConfig = config.useSingleServer();
        singleServerConfig.setAddress("redis://" + host + ":" + port).setPassword(password);
        return Redisson.create(config);
    }
    @Bean
    public RedissonClient getRedissonClient() {
        return new RedissonClient();
    }
}

  

  ApplicationContext工具类

package com.example.util;
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
 
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;
 
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        ApplicationContextHolder.context = context;
    }
 
    public static ApplicationContext getContext() {
        return context;
    }
}

  启动类

package com.example;
 
import com.example.entity.RedissonClient;
import com.example.util.RedisLockUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class DemoApplication {
    @Autowired
    private RedissonClient redissonClient;
 
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        RedisLockUtil.lock("Tony");
    }
 
}

  

标签:ApplicationContext,redissonClien,封装,springboot,--,博客,RedissonClient,import,publi
From: https://www.cnblogs.com/baicaowei/p/17557557.html

相关文章

  • Springboot JPA 集成多租户
    背景:​ iot-kit项目用的是jpa,不是mybatis,项目中需要引入多租户参考文章:【讲解多租户的实现与原理】https://www.bilibili.com/video/BV1F84y1T7yf/?share_source=copy_web&vd_source=981718c4abc87423399e43793a5d3763https://callistaenterprise.se/blogg/teknik/2020/10/17......
  • 属性的封装
    classAnimal{private_name:string;private_age:number;constructor(name:string,age:number){this._name=name;this._age=age;}sayHello(){console.log("hello");}getname(){......
  • 每日一题:SpringBoot中支持的事务类型
    以下是每种事务类型的作用、代码示例和对代码的解释:PROPAGATION_REQUIRED(默认):作用:如果当前存在事务,则方法将在该事务中运行;如果不存在事务,则创建一个新的事务。适用于大多数业务场景,确保方法在事务中执行,如果没有事务,则创建一个新的事务。代码示例:@Transactional(propagatio......
  • springboot配置2
    核心自动配置原理        @condition条件判断注解 如果没配过就给你配 依赖底层的condition注解 里面参数是条件配置类  红色的就是不满足条件的类 ......
  • springboot 配置
    配置文件yam 名字是固定的,yaml后缀也可以比XML更适合 大量的标记被浪费yml语法把空格玩到极致   如何编写yaml文件并绑定  只有这个组件是容器中的组件才能使用容器的功能@COmponent如何在properties编写 value配置对比     ......
  • springboot3
    通过maven项目构建springboot项目创建maven项目导入springboot依赖编写一个主程序 必须加上springboot注解 主函数的快捷键psvm;两个参数一个是主类,一个是主函数参数部署测试 打包成一个jar文件包,可以在命令行运行直接场景启动器  COntroller表现层包......
  • uni app 封装接api接口
    创建文件 base.jsletbaseURL='';//是否在控制台显示接口请求日志,本地环境启用,打包环境禁用letshowHttpLog=false;//测试环境baseURL='https://api.apiopen.top/api';//正式环境//baseURL='XXXXX.XXXXX.com';module.exports={baseURL:baseURL,......
  • vue3 封装api接口
    新建axiosj.tsimportaxiosfrom'axios';import{showMessage}from"./status";//引入状态码文件import{ElMessage}from'element-plus'//引入el提示框,这个项目里用什么组件库这里引什么//设置接口超时时间axios.defaults.timeout=60000;//请求地址,......
  • SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文,查询明文
    场景为防止数据泄露,需要在插入等操作时将某表的字段在数据库中加密存储,在需要查询使用时明文显示。ShardingSphereShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。......
  • [TSG开发日志4]算法组件、个人编写的库文件如何封装成DLL,如何更好地对接软件开发?
    写在前面这个内容确实是我有点疏忽了,我以为做算法的同事应该多少对这方面会有点了解的。但是我想了一下我刚毕业的时候,确实对这方面的理解不深,查了很多资料才勉强搞懂什么意思,也是后来随着工程学习的愈加深入,才渐渐了解了在C++开发中动态链接库的重要性及如何编写。一般在说一个......