1.什么是Spring
spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架
- 从大小与开销而言是轻量级的
- 通过控制反转的技术达到松耦合的目的
- 通过面向切面,允许通过分离应用的业务逻辑与系统即服务进行内聚性开发
- 包含并管理应用对象Bean的配置和生命周期,这个意义上是一个容器
- 将简单的组建配置,组合成复杂的应用,这个意义上是一个框架
2.谈谈你对AOP的理解
AOP--面向切面编程:能够将那些与业务无关的,但为业务模块所共用的一些逻辑,如(事务管理,日志管理)封装起来,减少重复代码,降低耦合,并有利于未来的可扩展性和可维护性。
Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,Spring AOP就会使用JDK动态代理去创建代理对象;对于没有实现接口的对象,无法使用JDK动态代理,而去使用CGlib动态代理生成一个被代理对象的子类来作为代理。使用AOP可以将一些通用功能抽象出来,如日志管理、事务管理和权限管理等,使用时直接调用即可,避免代码重复。
3.谈谈你对IoC(控制反转)的理解
- 1.容器概念:ioc容器,里面存放着各种对象,在项目启动时,读取配置文件里的bean节点,根据全限定类名使用反射放到容器中,此时容器里就有各种对象了,接下来在需要时,进行依赖注入。
- 2.控制反转:在没有引入ioc容器之前,对象A依赖于对象B,其中对象B的创建与使用的控制权掌握在A手中,在引入ioc容器之后,对象A与B之间失去了直接联系,当对象A运行到需要的对象B时,由IOC荣日主动创建对象B注入到A需要的地方。对象A获取依赖对象B的过程,从主动变为了被动,控制权颠倒,因此称为依赖反转。
- 3.依赖注入:控制反转之后,获取依赖对象的过程由自身管理变为了由IOC容器主动注入。依赖注入是实现IOC的方法,在容器运行期间,动态的将依赖关系注入到对象之中。
4.BeanFactory与ApplicationContext的区别
ApplicationContext是BeanFactory的子接口,ApplicationContext提供了更完整的功能
- 1.统一的资源文件访问方式
- 2.继承MessageSource,支持国际化
- 3.同时加载多个配置文件
区别
- BeanFactory采用延时加载来注入Bean,只有在用到某个Bean时,才对其实例化。这样就不能发现一些存在的Spring配置问题。
- ApplicationContext在容器启动时,一次性创建所有的Bean。在启动时就可以发现Spring中存在的配置问题,有利于检查依赖属性是否注入。
- 相比于BeanFactory,ApplicationContext唯一不足是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。
5.简述Spring中Bean的生命周期
- 1.解析类获取BeanDefinition
- 2.如果有多个构造方法,推断构造方法
- 3.确定好构造方法后,进行实例化获取对象
- 4.对对象中加了@Autowired注解的属性进行填充
- 5.回调Aware方法,如BeanNameAware
- 6.调用BeanPostProcessor初始化前的方法
- 7.调用初始化方法
- 8.调用BeanPostProcessor初始化后的方法,在这里进行AOP
- 9.如果创建的bean是单例会将bean放入单例池
- 10.使用Bean
- 11.spring关闭时,调用destroy()方法
6.解释一下Spring支持的几种Bean的作用域
- 1.singleton:Spring中默认的bean都是单例的,每个容器只有一个bean实例,该对象的生命周期与Spring IOC容器一致
- 2.prototype:为每一个bean请求创建一个实例
- 3.request:在每个http请求中创建一个单例对象,在单个请求中都会复用该对象,该 bean 仅在当前 HTTP request 内有效
- 4.session:在每个http请求中创建一个单例对象,该 bean 仅在当前 HTTP session 内有效
- 5.global-session:全局作用域,基于portlet 的 web 应⽤中才有意义,Spring5 已经没有了。
7.Spring框架中单例Bean是线程安全的吗?
不是线程安全的,框架并没有对bean进行多线程的封装处理。 主要是因为:当多个线程操作同一个对象时,对这个对象的非静态变量成员的写会存在线程安全问题。
解决方法:
- 1.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中
- 2.如果是多线程之间共享,需要使用lock、synchronized、CAS等实现线程同步的方法。
8.Spring框架中使用到了哪些设计模式
- 1.单例设计模式:Spring中的bean默认都是单例的
- 2.代理设计模式:Spring中AOP功能的实现
- 3.工厂设计模式:Spring使用工厂模式通过BeanFactory、ApplicationContext创建Bean对象
- 4.模板方法模式:Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使⽤到了模板模式;
- 5.包装器设计模式:项目需要链接不同的数据库,不同的客户在每次访问中去访问不同的数据库。
- 6.适配器模式:Spring中AOP的通知(Advice)使用了适配器模式。
9.Spring事务的实现方式和原理以及隔离级别
实现方式
事务的实现方式有两种:一种是编程式,一种是声明式,如使用@Transactional注解
原理 在一个方法上加了@Transactional注解之后,Spring基于这个类生成一个代理对象,将这个代理对象作为bean放入IOC容器,在调用代理对象方法时,如果方法存在@Transactional注解,那么代理兑奖事务的自动提交设置为false,再去执行原本的业务逻辑,如果没有异常,那么代理就会将事务提交,否则将事务回滚。
10.谈谈你对Spring中事务的理解以及Spring中的事务隔离级别
事务:是一个完整的业务逻辑,最小的工作单元,不可再分。要么同时执行成功,要么同时失败
事物的四个特性(ACID):
- 原子性:事务是最小的工作单元,不可分割
- 一致性:在同一个事务中,所有要求必须同时成功,或者同时失败,保证数据一致性
- 隔离性:当并发访问数据库时,一个是用户的事务不受其他事务的干扰,各并发事务之间的数据库是独立的
- 持久性:事务提交之后,它对数据库中数据的改变是持久的。
Spring中事物的隔离级别(四个)
- 1.读未提交--read uncommited(最低隔离级别) 问题:存在脏读现象
- 2.读已提交--read commited(Oracle数据库默认级别) 问题:不可重复读
- 3.可重复读--repeatable read(MySQL数据库默认级别) 问题:存在幻读现象
- 4.序列化--serializable(最高隔离级别) 问题:不能并发,效率最低
11.Spring中的事务传播行为
事务传播⾏为是为了解决业务层⽅法之间互相调⽤的事务问题。当事务⽅法被另⼀个事务⽅法调⽤时,必须指定事务应该如何传播。
支持当前事务的情况:
- REQUIRED(默认):如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务;
- SUPPORTS:如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏;
- MANDATORY:如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。
不支持当前事务的情况:
- REQUIRES_NEW:创建⼀个新的事务,如果当前存在事务,则把当前事务挂起;
- NOT_SUPPORTED::以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。
- NEVER:以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常
其他情况
NESTED:如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于REQUIRED
12.spring事务什么时候会失效
- 1.发生自调用,类里面使用this调用本类的方法,此时这个this对象不是代理类。
- 2.方法不是public的,@Transactional只能用在public的方法上,否则方法不会生效,如果非要用在不是public的方法上,开启AspectJ代理模式
- 3.数据库不支持事务
- 4.没有被spring管理
- 5.异常被吃掉,事务不会回滚
13.bean的自动装配有哪些方式?
五种
- 1.no-手动配置,通过'ref'手动设定
- 2.byName,通过bean的属性名称自动装配
- 3.byType,通过bean的类型进行自动装配
- 4.constructor,通过bean的类型与构造器参数相同进行装配
- 5.autodetect,如果有默认构造器,则通过constructor进行自动装配,否则使用byType自动装配
-END-