Spring底层源码的理解和学习

一、Spring框架中Bean的创建过程是怎样的?

首先,简单来说,Spring框架中的Bean经过四个阶段:实例化-》 属性赋值-》初始化-》 销毁
然后:具体来说,Spring中Bean 经过了以下几个步骤:
1、实例化new xaa0;两个时机:1、当客户端向容器申请一个Bean时,2、当容器在初始化一个Bean时发现还需要依赖另一个Bean。 BeanDefinition 对象保存。-到底是new一个对象还是创建一个动态代理?
2、设置对象属性(依赖注入):Spring通过BeanDefinition找到对象依赖的其他对象,并将这些对象赋予当前对象。
3、处理Aware接口:Spring会检测对象是否实现了xxxAware接口,如果实现了,就会调用对应的方法。
BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, ApplicationContextAware
4、BeanPostProcessor前置处理:调用BeanPostProcessor的postProcess Beforelnitialization方法
5、lnitializing Bean: Spring检测对象如果实现了这个接口,就会执行他的afterPropertiesSet0方法,定制初始化逻辑。
6、init-method: sbean init-method=xxx>如果Spring发现Bean配置了这个厲性,就会调用他的配置方法,执行初初始化逻辑。@PostConstruct
7、BeanPostProcessor后置处理:调用BeanPostProcessor的postProcessAfterlnitialization方法。
到这一步,这个Bean的创建过程就完成了,Bean就可以正常使用了。
8、DisposableBean:当Bean实现了这个接口,在对象销毁前就会调用destory0方法。
9、destroy-method: sbean destroy-method=xxx>@PreDestrov

二、Spring框架中的Bean是线程安全的吗?如果线程不安全,要如何处理?

Spring容器本身没有提供Bean的线程安全策略,因此,也可以说Spring容器中的Bean不是线程安全的。要如何处理线程安全问题,就要分情况来分析。
Spring中的作用域: 1、sington 2、prototype:为每个Bean请求创建给实例。3、request:为每个request请求创建个实例,请求完成后失效。 4、 session:与request是类似的。5、global-session:全局作用域。
对于线程安全问题:
1>对于prototype作用域,每次都是生成一个新的对象,所以不存在线程安全问题。
2>sington作用域:默认就是线程不完全的。但是对于开发中大部分的Bean,其实是无状态的,不需要保证线程安全。所以在平常的MVC开发中,是不会有线程安全问题的。
无状态表示这个实例没有属性对象,不能保存数据,是不变的类。比如:controller、service、 dao。
有状态表示示例是有属性对象,可以保存数据,是线程不安全的,比如 pojo。

但是如果要保证线程安全,可以将Bean的作用域改为prototype 比如像 Model View。
另外还可以采用ThreadLocal来解决线程安全问题。ThreadLocal为每个线程保存一个副本变量,每个线程只操作自己的副本变量。

三、Spring如何处理循环依赖问题?

在这里插入图片描述

循环依赖:多个对象之问存在循环的引用关系,在初始化过程当中,就会出现"先有蛋还是先有鸡"的问题。

  1. @Lazy注解:解决构造方法造成的循环依赖问题

  2. 三级缓存
    对于对象之间的普通引用,
    二级缓存会保存new出来的不完整对象,这样当单例池中找到不依赖的属性时,就可以先从二级缓存中获取到不完整对象,完成对象创建,在后续的依赖注入过程中,将单例池中对象的引用关系调整完成。
    三级缓存:如果引用的对象配置了AOP,那在单例池中最终就会需要注入动态代理对象,而不是原对象。而生成动态代理是要在对象初始化完成之后才开始的。于是Spring增加三级缓存,保存所有对象的动态代理配置信息。在发现有循环依赖时,将这个对象的动态代理信息获取出来,提前进行AOP,生成动态代理。
    一个对象要么以一个完整对象存在于二级缓存中,要么以一个ObjectFactory(配置信息)存在于三级缓存中。
    在这里插入图片描述

  3. 核心代码就在DefaultSingletonBeanRegistry的getSingleton方法当中。
    在这里插入图片描述

四、Spring如何处理事务?事务传播机制?隔离级别?Spring事务什么时候会失效?

Spring当中支持编程式事务管理和声明式事务管理两种方式:
1、编程式事务可以使用TransactionTemplate。
2、声明式事务:是Spring在AOP基础上提供的事务实现机制。他的最大优点就是不需要在业务代码中添加事务管理的代码,只需要在配置文件中做相关的事务规则声明就可以了。但是声明式事务只能针对方法级别,无法控制代码级别的事务管理。

Spring中对事务定义了不同的传播级别: Propagation
1、 PROPAGATION_ REQUIRED:默认传播行为。如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入到事务中。
2、PROPAGATION SUPPORTS: 如果当前存在事务,就加入到该事务。如果当前不存在事务,就以非事务方式运行。
3、PROPAGATION_ MANDATORY:如果当前存在事务,就加入该事务。如果当前不存在事务,就抛出异常。
4. PROPAGATION REQUIRES NEW
5、PROPAGATION NOT_ SUPPORTED:以非事务方式运行。如果当前存在事务,就将当前事务挂起。
6、PROPAGATION NEVER:以非事务方式运行。如果当前存在事务,就抛出异常。
7、PROPAGATION NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则按REQUEIRED属性执行。

Spring中事务的隔离级别:
1、ISOLATION_DEFAULT:使用数据库默认的事务隔离级别。
2、ISOLATION READ_UNCOMMITTED:读未提交。允许事务在执行过程中,读取其他事务未提交的数据。
3、ISOLATION_READ_COMMITTED:读已提交。允许事务在执行过程中,读取其他事务已经提交的数据。
4、ISOLATION_ REPEATABLE READ:可重复读。在同一个事务内,任意时刻的查询结果是一致的。
5, ISOLATION SERIALIZABLE:所有事务依次执行。

spring事务的原理是AOP,进行了切面增强,那么失效的根本原因是这个AOP不起作用了!常见情况有如下几种
1、发生自调用,类里面使用this调用本类的方法(this通常省略),此时这个this对象不是代理类,而是UserService对象本身!
解决方法很简单,让那个this变成UserService的代理类即可!
2、方法不是public的
3、数据库不支持事务
4、没有被spring管理
5、异常被吃掉,事务不会回滚(或者抛出的异常没有被定义,默认为RuntimeException)

五、SpringMVC中的控制器是不是单例模式?如果是,如何保证线程安全?

控制器是单例模式。
单例模式下就会有线程安全问题。
Spring中保证线程安全的方法:
1、将scop设置成非singleton。 prototype, request。
2、最好的方式是将控制器设计成无状态模式。在控制器中,不要携带数据。但是可以引用无状态的service和dao。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱喝皮蛋瘦肉粥的小饶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值