最近在自己试着搭个框架的时候用得是Springboot,整合了thrift,shiro,redis,redis集群我在本地搞了一个集群,我的本意是,用户在请求的时候会被拦截,在拦截器中定义不需要拦截的路径,其实shiro也是一个拦截器,但是我在shiro中只负责鉴权和权限分配,我想登陆的时候把一些用户的信息保存在redis缓存里,但是在拦截器中注入的redis服务总是获取的null,就是redis服务没有注入进来。
找了各种原因,包扫描,甚至怀疑自己服务写的有问题。。。。,然后把服务换成了JedisCluster,发现还是注入不了,后面实在不行把redis服务写到controller里发现可以注入,然后问题就被定位到了,发现是这个拦截器有问题,网上百度了一下,有人也遇到同样的问题,但是找了各种答案都解释的不太清楚,找了各种资料,以下是我的理解,不对的地方,多多指教。
先看拦截的代码,红色的框是我后来修改正确的代码,黄色的框是我之前写的代码
Spring在容器加载的时候会根据注解和xml创建各种bean,如果是注解没写bean的作用域默认是单例模式,
单例模式的作用域:单例模式,Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象。Singleton作用域是Spring中的缺省作用域,也可以显示的将Bean定义为singleton模式。
但是我写的代码黄色部分的,是通过new一个对象,spring boot容器在启动的时候,会默认扫描application所在的包的注解,我的项目结构很多模块,不是集成在一个maven工程里,也扫描了autowired注入的redis服务这个拦截器暂且给它命名个名字对象A,当发生登陆请求的时候,首先会经过拦截器,在拦截器栈里是new了一个拦截器对象,所以这个对象并不是A,所以当打入断点调入这个拦截器的时候,再注入redis服务所以才会空,bean注入只在容器初始化的时候注入。那么我在这个拦截器上面加个注解Component注解可不可以了,是不可以的,Spring boot在扫描的时候虽然能扫描到,但是注入的对象和上面情况一样,不是同一bean,
最好的方式就是上面红色框子写的代码,通过@bean的方式注入bean,下面黄色部分代码不能通过new 创建一个对象了,直接调用上面的get方法
最后成功注入redis
Springboot在初始化容器的时候通过注解的扫描创建了共享bean实例,在发生url请求拦截的时候,不会在创建新的对象,从容器中取了已经注入服务的bean。
最后附上redis集群