一、Spring是如何处理线程的并发问题的?

在Spring中,大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal解决线程安全问题

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。

1. 同步机制采用了“**时间换空间**”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。

2. ThreadLocal采用了“**空间换时间**”的方式,ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

二、解释Spring支持的几种bean的作用域

(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用**getBean()时,相当于执行newXxxBean()。
(3)
request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)
session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效**。
(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

三、singleton和prototype的区别是什么?

(1) singleton在容器中,只被实例化一次,而prototype在容器中,调用几次,就被实例化几次
(2) 在AppplicationContext容器中,singleton在applicaitonContext.xml加载时就被预先实例化而prototype必须在调用时才实例化。
**

四、什么是AOP?它的作用是什么?有什么好处?

(1) AOP:面向切面编程
(2) 利用AOP可以对业务逻辑的各个部分进行隔离,降低耦合度,提高程序的可用性,同时也提高了开发的效率。

五、Spring AOP 的动态代理是什么?

为了在不改变原始代码的情况下,将某个代码动态的切入到指定的方法指定的位置中。

1.JDK动态代理底层实现

1.JDK动态代理是通过java.lang.reflect.Proxy类来实现的
2.创建一个代理类,首先要让代理类去实现InvocationHandler接口,并实现该接口的invoke(),所有动态代理调用的方法都会交给该方法来处理
3.在创建代理对象方法中,使用Proxy类的静态方法newProxyInstance()方法来创建代理对象,该方法有三个参数,第一个参数是当前类的类加载器,第二个参数是被代理对象实现的所有接口,第三个是当前代理类本身
4.在invoke()方法中目标方法执行的前后去执行切面类的方法


2.JDK动态代理有什么缺点?

1.每一个业务类都要写自己的代理对象
2.如果被代理对象没有实现接口就没办法实现动态代理


3.Spring AOP 是如何实现动态代理?

底层就是 JDK动态代理的方式实现的!

4.AOP术语

切面(Aspect)
哪些对象、方法要增强
连接点(JoinPoint)
可以被增强的方法
切入点(PointCut)
实际真正被增强的方法
通知(Advice)
前置通知(Before)
后置通知(AfterReturnning)
环绕通知(Around)
异常通知(AfterThrowing)
最终通知(After)

无异常执行顺序: 环绕之前 -> 前置通知 -> 业务方法 -> 环绕之后 -> 最终通知 -> 后置通知
异常执行顺序: 环绕之前 -> 前置通知 -> 业务方法执行出异常 -> 最终通知 -> 异常通知


目标对象(Target)
代理(Proxy)

六、Spring 事务的管理

1.事务的四个特性分别是什么ACID?

原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

一致性(Consistency)一个事务中,事务前后数据的完整性必须保持一致。

隔离性(Isolation)多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的

2.事务的并发会产生的问题有哪些?

1) 脏读
事务读取了另一个事务未提交的数据,但是另一个事务回滚了
一个事务正在对数据进行更新操作,但是更新还未提交,另一个事务这时也来操作这组数据,并且读取了前一个事务还未提交的数据,而前一个事务如果操作失败进行了回滚,后一个事务读取的就是错误的数据,这样就造成了脏读

2)不可重复读(修改删除)
事务第二次查询之前,有另一个事务修改了数据,导致事务两次查询的数据不同
一个事务多次读取同一个数据,在该事务还未结束时,另一个事务也对该数据进行了操作,而且在第一个事务两次读取之间,第二个事务对数据进行了更新,那么第一个 事务前后两个读取到的数据是不同的,这样就造成了不可重复读

3) 幻读(新增)
事务第二次查询之前,另一个事务又插入了一条符合条件的数据,导致第二次查询的数据比第一次查询时多了
第一个数据正在查询某一条数据,这时,另一个事务又插入了一条符合条件的数据,第一个事务在第二次查询符合同一条件的数据时,发现多了一条前一次查询时没有的数据,仿佛幻觉一样,这就是幻读

3.事务的隔离级别有哪些?

数据库的默认隔离级别
Oracle:read_committed
Mysql:repeatable_read

1)default:(默认)
默认隔离级别,使用数据库默认的事务隔离级别
2)read_uncommitted:(读未提交)
这是事务最低的隔离级别,他允许另外一个事务可以看到这个事务未提交的数据,这种隔离级别会产生脏读,不可重复读和幻读
3)read_committed:(读已提交)
保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据.这种事务隔离级别可以避免脏读,但是可能会出现不可重复读和幻读
4)repeatable_read:(可重复读)
这种事务级别可以防止脏读,不可重复读.但是可能出现幻读.他除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读
5)Serializable 串行化
这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。防止了脏读、不可重复读、幻读
事务的隔离级别会产生的问题列表.png

八、什么是事务的传播行为?propagation

事务的传播行为.png

九、spring的事务什么情况下会失效?

1)使用默认的事务处理方式
因为在java的设计中,它认为不继承RuntimeException的异常**是”checkException”或普通异常,如IOException,这些异常在java语法中是要求强制处理的。对于这些普通异常,spring默认它们都已经处理,所以默认不回滚。可以添加rollbackfor=Exception.class来表示所有的Exception都回滚。
2)内部调用**
不带事务的方法调用该类中带事务的方法,不会回滚。因为spring的回滚是用过代理模式生成的,如果是一个不带事务的方法调用该类的带事务的方法,直接通过this.xxx()调用,而不生成代理事务,所以事务不起作用。常见解决方法,拆类。


1.为什么失效?

JDK的动态代理。只有被动态代理直接调用时才会产生事务。在SpringIOC容器中返回的调用的对象是代理对象而不是真实的对象。而这里的this是EmployeeService真实对象而不是代理对象。

2.如何解决?

1)手动cache异常,并抛出一个运行时异常
2)添加动态代理,用代理对象去调用内部方法