javaee学习问题

1.sql的url配置

Spring 循环依赖:简单来说就是自己依赖自己,或者和别的Bean相互依赖。A依赖B,B依赖A,构成一个闭环。

jdbc:mysql://localhost:3306/mybatis?
useSSl=true&
useUnicode=true&
characterEncoding=UTF-8&
serverTimezone=GMT

问题描述

提示The server time zone value '????????' is unrecognized or represents more than one time zone就是时区错误。


解决问题:

添加serverTimezone=GMT即可。

2.mybatis查询结果为null时返回不包含


问题描述

mybatis在给map赋值时,如果返回值不是基本数据类型,且返回值为null,就不会处理这个字段,不会将字段的值映射到map中。也就是说返回的map中是没有这个字段的,当结果返回的时候,调用get方法,就直接调用了字段设置的默认值0。


解决问题:

在application.yml配置中添加配置call-setters-on-nulls: true,让mybatis在给map参数映射的时候连null值也一并带过来。

3.循环依赖问题:

Spring 循环依赖:简单来说就是自己依赖自己,或者和别的Bean相互依赖。A依赖B,B依赖A,构成一个闭环。


问题描述

只有单例的Bean才存在循环依赖的情况,原型(Prototype)情况下,Spring会直接抛出异常。原因就是,AB循环依赖,A实例化的时候,发现依赖B,创建B实例,创建B的时候发现需要A,创建A1实例……无限套娃,系统就会垮掉。


方法分析:

单例Bean初始化完成,要经历三步:实例化、属性赋值、初始化

注入就发生在第二步,属性赋值,结合这个过程,Spring 通过三级缓存解决了循环依赖:

一级缓存 : Map<String,Object> singletonObjects,俗称“单例池”“容器”,用于保存实例化、属性赋值(注入)、缓存创建完成单例Bean的地方。

二级缓存 : Map<String,Object> earlySingletonObjects,早期曝光对象,映射Bean的早期引用,也就是说在这个Map里的Bean不是完整的,甚至还不能称之为“Bean”,只是一个Instance用于保存实例化完成的 bean 实例。

三级缓存 : Map<String,ObjectFactory<>> singletonFactories,早期曝光对象工厂,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。


解决过程:

当 A、B 两个类发生循环依赖时:

A实例的初始化过程:

  1. 创建A实例,实例化的时候把A对象工厂放入三级缓存,表示A开始实例化了。

  2. A注入属性时,发现依赖B,此时B还没有被创建出来,所以去实例化B

  3. 同样,B注入属性时发现依赖A,它就会从缓存里找A对象。依次从一级到三级缓存查询A,从三级缓存通过对象工厂拿到A,发现A虽然不太完善,但是存在,把A放入二级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入一级缓存。

  4. 接着A属性赋值,从一级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除⼆级缓存中的A,同时把A放入一级缓存

  5. 最后,一级缓存中保存着实例化、初始化都完成的A、B对象

结论:

在Spring中有很多方法可以处理循环依赖。首先要考虑的是重新设计bean,这样就不需要循环依赖:它们通常是可以改进的设计的症状。

但是如果你的项目中绝对需要循环依赖,则可以使用三级缓存。三级缓存的目的是为了在没有循环依赖的情况下,延迟代理对象的创建,使 Bean 的创建符合 Spring 的设计原则。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值