你一直在用Spring,但你可能真的不懂它

你一直在用Spring,但你可能真的不懂它

本文于2020-04-24进行重构

看我的文章,如果关于某些定义觉得读完不太明白,那是正常的,我会在后面进行阐述,尽量用自己的理解,使用大白话,讲清楚

任何学习都是一样,不要纠结于一处,也许学到后面,再回过头来看,一目了然了呢

Spring的专题我做了分离,本文旨在"让你更懂Spring"

实操分离:

Spring控制反转操作

Spring面向切面AOP操作

Spring事务管理操作

相关:

Spring MVC

WHAT IS SPRING

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。

它是为了解决企业应用开发的复杂性而创建的,框架的主要优势之一就是其分层架构分层架构允许使用者选择使用哪一个组件同时为 J2EE 应用程序开发提供集成的框架。

Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

Spring的核心是控制反转(IoC)面向切面(AOP)

简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架

重要的Spring framworks

这是Spring的架构图,它包含以下重要组件

Spring Data Access 数据相关组件模块:

  • Spring JDBC : Java数据库连接
  • Spring ORM : 用于支持Hibernate等ORM工具
  • Spring JMS :Java消息服务
  • Spring Transactions:事务管理组件

Spring Web模块

  • 这块是Spring MVC的内容

Core Containner 容器相关模块

  • Spring Beans:实体类的容器组件

  • Spring Core: Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能

  • Spring Context:Spring上下文组件,Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能

其他:

  • Spring AOP :提供了面向切面的编程实现
  • Spring Test : 提供了对 JUnit 和 TestNG 测试的支持

控制反转(IOC)

IOC是Spring为Java提供的一种全新的设计思想,这也是Spring提出的核心思想,也是Spring为我们做的一件了不起的事情!

控制反转(Inversion of Control),就是应用本身不负责对象的创建(new object())和维护对象和依赖对象创建完全交给Spring的容器去管理和维护,这个权利反转给容器

在学习Spring 之前,所有我们需要用到对象,都由我们手动new,如

new DaoImpl();

这样做,在项目开发中有很大的问题:

带来了很大的耦合性,项目不好维护,测试成本也高

每次用到对象,都要new,那为何不把这个对象放到容器中,我们用到的时候,直接去取呢?所以,我们把new对象这件事就交给了Spring,即所谓的控制反转,将对对象的控制权反转给Spring的容器

Spring 早期时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置过于繁琐,于是

SpringBoot 时代,注解配置就慢慢开始流行起来,到现在,基本已经成为Spring的主流玩法

面向切面(AOP)

AOP(Aspect-Oriented Programming:面向切面编程)

这也是一种伟大的设计思想,它能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可拓展性和可维护性

很简单,想想你是否在基础的Web学习中学过拦截器,拦截器就是AOP思想的主要应用了

AOP(Aspect Oriented Programming),通过预编译的方式在运行期使用动态代理的方式来实现的一种技术

动态代理是一个核心设计思想,你最好能够掌握它,才能更好的理解Spring

关于动态代理,可以参考我之前些的一篇Blog:

代理模式

Bean

你可以将之理解为我们创建的对象,对象即Bean

Spring通过容器,存储我们需要创建对象,并针对这些对象,构建了一套完整的生命周期

Bean作用域?

Spring为我们创建的对象,有不同的类型,不同类型的Bean特性不同,具体:

  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的
  • prototype : 每次请求都会创建一个新的 bean 实例
  • request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  • session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效
  • global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。

单例Bean的线程安全问题?

大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题

解决方法:

在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中

bean的生命周期?

我们必须知道,Bean是何时被容器创建出来的,又是何时被销毁的,我们先要知道bean是如何被创建出来的

下图是Bean被创建的过程

  • Bean 容器找到配置文件中 Spring Bean 的定义。
  • Bean 容器利用 Java Reflection API 创建一个Bean的实例。
  • 如果涉及到一些属性值 利用 set()方法设置一些属性值。
  • 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。
  • 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
  • 与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。
  • 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
  • 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
  • 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
  • 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
  • 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

关于Spring中的设计模式

目前,我还没整理出我学习的设计模式的笔记心得,有机会的话,我会做一期设计模式的专栏

下面列举一些Spring中的设计模式

  • 工厂设计模式 : Spring使用工厂模式通过 BeanFactoryApplicationContext 创建 bean 对象
  • 代理设计模式 : Spring AOP 功能的实现,Spring使用的是JDK动态代理模式
  • 单例设计模式 : Spring 中的 Bean 默认都是单例的
  • 模板方法模式 : Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式
  • 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源
  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用
  • 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller

Spring事务

这里你应该想想数据库中的事务概念了,在数据库中,我们需要用到Spring的事务管理!

在我之前谈到Mysql的锁的时候,我详细介绍了有关事务内容,可以复习一下

你真的懂Mysql的锁吗?详谈Myql的锁机制

Spring管理事务的方式分为:

  1. 编程式事务,在代码中硬编码。(不推荐使用)
  2. 声明式事务,在配置文件中配置**(推荐使用)**
    1. 基于XML的声明式事务
    2. 基于注解的声明式事务**(推荐使用)**

Spring事务隔离级别

TransactionDefinition 接口中定义了五个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  • TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  • TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
原创文章 197 获赞 142 访问量 6万+

猜你喜欢

转载自blog.csdn.net/JunSIrhl/article/details/105740889