Spring IOC

没有IOC的情况

在没有IOC的情况下,Servlet使用一个service类需要在代码内部显示创建对象,例如下图。如果有多个Servlet同时需要依赖MyService接口调用方法,此时代码的耦合度就会太高。因为后期如果Servlet类调用的是实现MyService接口的NewMyServiceImpl类的话,就导致需要在Servlet类里手动调整。可能会造成错误。(改动代码成本大,改动完的测试成本也很大)。
归根结底,就是代码里各种类之间完全耦合在一起,出现一丁点的变动,都需要改动大量的代码,重新测试,可能还会出现bug。

  1. public class MyServlet {
  2. private MyService myService = new MyServiceImpl();
  3. }
  4. public interface MyService {
  5. }
  6. public class MyServiceImpl implement MyService {
  7. }
  8. public class NewMyServiceImpl implement MyService {
  9. }

Spring IOC

控制反转,依赖注入。
基于注解或者xml文件,将类交由Spring容器工厂。Spring容器根据xml或者注解,去实例化你的一些bean对象,然后根据xml配置或者注解,去对bean对象之间的引用关系,去进行依赖注入,某个bean依赖另外一个bean。
底层核心技术:反射。通过反射技术,直接根据你的类去自己构建对应的对象出来。
系统的类与类之间彻底的解耦合。

  1. public class MyServlet {
  2. @Resource
  3. private MyService myService;
  4. }
  5. // @Service
  6. public class MyServiceImpl implement MyService {
  7. }
  8. @Service
  9. public class NewMyServiceImpl implement MyService {
  10. }

Spring AOP

概念与案例

面向切面编程
有时候,会有多个类的方法都用同样的代码,比如事务代码,都需要有事务开启代码,事务提交代码,事务回滚代码等,此时就可以通过使用AOP,将相同的代码切面出去。后面在执行类的方法的时候,都会去植入一些代码,在所有这些方法刚开始运行的时候,都会去做一些相同的事情(比如开启事务),在所有这些方法运行完毕之后,去根据是否抛出异常等信息去执行植入一些代码(比如提交事务,回滚事务等)。

基于Spring AOP如何切面

AOP的核心原理

动态代理技术。
动态代理相关知识请查阅【java的三种代理方式】。

动态代理

动态代理:其实就是动态地创建一个代理类出来,然后创建这个代理类的实例对象,在代理类对象里面引用委托类,所有的方法的调用,都是先走代理类的对象,它负责做一些代码的增强,再去调用你写的类方法。

Spring AOP使用的就是动态代理技术。
(1)如果你的类实现了某个接口,spring aop会使用jdk动态代理,生成一个跟你实现了同一个接口的代理类,构造一个示例对象出来。
(2)如果你的类没有实现接口,spring aop会改用cglib动态代理,生成一个委托类的子类作为代理类,cglib动态代理可以动态生成字节码,覆盖你的一些方法,在方法里加入增强的代码。

Spring Bean是线程安全的吗

Spring容器bean范围

(1) singleton: 默认,每个容器只有一个bean实例
(2) prototype: 为每一个bean请求提供一个实例
(3) request: 为每一个网络请求创建一个实例,在请求完成
(4) session: 与request范围类似。确保每个session中有一个bean实例,在session过期后,bean就会失效
(5) global_session

Spring Bean不是线程安全

一般来说很少在spring bean存放一些实例变量,一般来说他们都是多个组件互相调用,最终去访问数据库。

  1. @Service
  2. public class MyServiceImpl implement MyService {
  3. public void doService() {
  4. }
  5. }
  6. @Controller
  7. public class MyController {
  8. @Resource
  9. private MyService myService;
  10. public void doRequest() {
  11. myService.doService();
  12. }
  13. }

Spring的事务实现原理和传播机制

事务实现原理

当在代码中加入@Transactional注解,此时spring会使用AOP思想,对你的方法在执行之前,先去开启事务,执行完毕之后,根据你的方法是否报错,来决定回滚或者提交事务。

事务传播机制

  1. @Transactional(propagation = Propagation.REQUIRED)
  2. (1)Propagation.REQUIRED: 如果当前没有事务,就创建一个事务,如果当前存在事务,就加入该事务。(最常用设置)
  3. (2)Propagation.SUPPORTS: 支持当前事务,如果当前存在事务,就加入该事务,否则就以非事务执行。
  4. (3)Propagation.MANDATORY: 支持当前事务,如果当前存在事务,就加入该事务,否则就抛出异常。
  5. (4)Propagation.REQUIRED_NEW: 创建新事务,无论当前存不存在事务,都创建新事务。
  6. (5)Progation.NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  7. (6)Progation.NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
  8. (7)Progation.NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
  9. 嵌套事务:外层的事务如果回滚,会导致内层的事务也回滚;但是内层的事务如果回滚,仅仅回滚自己的代码。
  10. @Transactional(propagation = Propagation.REQUIRED)
  11. public void methodA() {
  12. doSomethingPre();
  13. methodB();
  14. doSomethingPost();
  15. }
  16. @Transactional(propagation = Propagation.NESTED)
  17. public void methodB {
  18. //to do something
  19. }