Spring

前言

  • Spring 是最受欢迎的企业级 Java 应用程序开发框架,数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。

  • Spring 框架是一个开源的 Java 平台,它最初是由 Rod Johnson 编写的,并且于 2003 年 6 月首次在 Apache 2.0 许可下发布。

  • Spring 是轻量级的框架,其基础版本只有 2 MB 左右的大小。

  • Spring 框架的核心特性是可以用于开发任何 Java 应用程序,但是在 Java EE 平台上构建 web 应用程序是需要扩展的。

  • Spring 官网

  • Spring 教程

  • Spring 快速入门

1、Spring

  • Spring 是一个基于 IOC(Inversion Of Control,反转控制)和 AOP(Aspect Oriented Program,面向切面编程)结构的 J2EE 系统的框架,目标是使 J2EE 开发变得更容易使用。

    • Spring 是全面的和模块化的。
    • Spring 致力于提供一种方法管理你的业务对象。
    • 它定位的领域是许多其他流行的 framework 没有的。
    • 通过启用基于 POJO(Plain Old Java Objects,普通老式 Java 对象)编程模型来促进良好的编程实践。
  • 三层架构

    • A 表现层:web 层,MVC 是表现层的一个设计模型
    • B 业务层:service 层
    • C 持久层:dao 层
  • 特性

    • 非侵入式:基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API。
    • 控制反转:IOC——Inversion of Control,指的是将对象的创建权交给 Spring 去创建。使用 Spring 之前,对象的创建都是由我们自己在代码中 new 创建。而使用 Spring 之后。对象的创建都是给了 Spring 框架。
    • 依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用 setXX 方法去设置,而是通过配置赋值。
    • 面向切面编程:Aspect Oriented Programming——AOP。
    • 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期。
    • 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用 XML 和 Java 注解组合这些对象。
    • 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上 Spring 自身也提供了表现层的 SpringMVC 和持久层的 Spring JDBC)。
  • 特点

    • 方便解耦,简化开发。Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给 Spring 管理。
    • 方便集成各种优秀框架。Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持。
    • 降低 Java EE API 的使用难度。Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低。
    • 方便程序的测试。Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序。
    • AOP 编程的支持。Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能。
    • 声明式事务的支持。只需要通过配置就可以完成对事务的管理,而无须手动编程。
  • Spring MVC 和 Spring Boot 都属于 Spring。

    • Spring MVC 是基于 Spring 的一个 MVC 框架,主要用于开发 WEB 应用和网络接口,它是 Spring 的一个模块。
    • Spring Boot 是基于 Spring 的一套快速开发整合包,它的目的在于实现自动配置,降低项目搭建的复杂度。

    • Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具。

  • Spring Boot 相当于一个大的框架,里面包含了包括 Spring 在内的其他东西,Spring MVC 又仅仅是 Spring 当中处理 Web 层请求的一个模快,所以,整体上来说,三者之间的关系大概为:Spring Boot > Spring > Spring MVC

1.1 体系结构

  • Spring 是模块化的,允许你挑选和选择适用于你的模块,不必要把剩余部分也引入。

  • Spring 框架提供约 20 个模块,可以根据应用程序的要求来使用。

  • Spring 框架包含 核心容器、数据访问/集成层、Web 层、Test 模块和 其他一些重要的模块

1.1.1 核心容器

  • 核心容器由 spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring 表达式语言,Spring Expression Language)等模块组成,它们的细节如下:

    • spring-core 模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。

    • spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。

    • context 模块建立在由 core和 beans 模块的基础上建立起来的,它以一种类似于 JNDI 注册的方式访问对象。Context 模块继承自 Bean 模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过 Servelet 容器)等功能。Context 模块也支持 Java EE 的功能,比如 EJB、JMX 和远程调用等。ApplicationContext 接口是 Context 模块的焦点。spring-context-support 提供了对第三方集成到 Spring 上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。

    • spring-expression 模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是 JSP2.1 规范中定义的统一表达式语言的扩展,支持 set 和 get 属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从 Spring IoC 容器检索对象,还支持列表的投影、选择以及聚合等。

  • 它们的完整依赖关系如下图所示

1.1.2 数据访问/集成 层

  • 数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:

    • JDBC 模块提供了 JDBC 抽象层,它消除了冗长的 JDBC 编码和对数据库供应商特定错误代码的解析。

    • ORM 模块提供了对流行的对象关系映射 API 的集成,包括 JPA、JDO 和 Hibernate 等。通过此模块可以让这些 ORM 框架和 spring的其它功能整合,比如前面提及的事务管理。

    • OXM 模块提供了对 OXM 实现的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream 等。

    • JMS 模块包含生产(produce)和消费(consume)消息的功能。从 Spring 4.1 开始,集成了 spring-messaging 模块。

    • 事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。(注:编程式事务需要自己写 beginTransaction()、commit()、rollback() 等事务管理方法,声明式事务是通过注解或配置由 spring 自动处理,编程式事务粒度更细)

  • (JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)。

1.1.3 Web 层

  • Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:

    • Web 模块提供面向 web 的基本功能和面向 web 的应用上下文,比如多部分(multipart)文件上传功能、使用 Servlet 监听器初始化 IoC 容器等。它还包括 HTTP 客户端以及 Spring 远程调用中与 web 相关的部分。

    • Web-MVC 模块为 web 应用提供了模型视图控制(MVC)和 REST Web服务的实现。Spring 的 MVC 框架可以使领域模型代码和 web 表单完全地分离,且可以与 Spring 框架的其它所有功能进行集成。

    • Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。

    • Web-Portlet 模块提供了用于 Portlet 环境的 MVC 实现,并反映了 spring-webmvc 模块的功能。

1.1.4 Test 模块

  • Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。

1.1.5 其他 模块

  • 还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:

    • AOP 模块提供了面向方面(切面)的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。

    • Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。

    • Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。

    • Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。

    • 测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。

1.2 配置

  • 环境配置

  • 实例

  • 新建 applicationContext.xml:是 Spring 的核心配置文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean name="c" class="com.how2java.pojo.Category"> <!-- 定义关键字 c -->
    <property name="name" value="category 1" />
    </bean>

    </beans>
  • 通过关键字 c 即可获取 Category 对象,该对象获取的时候,即被注入了字符串 “category 1“ 到 name 属性中。

    1
    2
    3
    4
    5
    6
    7
    public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });

    Category c = (Category) context.getBean("c"); // 通过关键字 c 获取 Category 对象

    System.out.println(c.getName()); // 输出 category 1
    }
  • 基本原理:

    • 传统的方式:

      • 通过 new 关键字主动创建一个对象。
    • IOC 方式:

      • 对象的生命周期由 Spring 来管理,直接从 Spring 那里去获取一个对象。

2、IOC 反转控制

  • 反转控制 IOC —— Inversion of Control,指的是将对象的创建权交给 Spring 去创建。是 Spring 的基础。使用 Spring 之前,对象的创建都是由我们自己在代码中 new 创建。而使用 Spring 之后,对象的创建都是给了 Spring 框架。

  • IOC 容器是具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。在 Spring 中 BeanFactory 是 IOC 容器的实际代表者。

  • Spring IoC 容器利用 Java 的 POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。下图是 Spring 如何工作的高级视图。

3、DI 依赖注入

  • 依赖注入 DI —— Dependency Injection,是指依赖的对象不需要手动调用 setXX 方法去设置,而是通过配置赋值。简单地说就是拿到的对象的属性,已经被注入好相关值了,直接使用即可。

  • Spring 框架的核心功能之一就是通过依赖注入的方式来管理 Bean 之间的依赖关系。

  • Spring 最认同的技术是控制反转的依赖注入(DI)模式。控制反转(IoC)是一个通用的概念,它可以用许多不同的方式去表达,依赖注入仅仅是控制反转的一个具体的例子。

  • 当编写一个复杂的 Java 应用程序时,应用程序类应该尽可能的独立于其他的 Java 类来增加这些类可重用可能性,当进行单元测试时,可以使它们独立于其他类进行测试。依赖注入(或者有时被称为配线)有助于将这些类粘合在一起,并且在同一时间让它们保持独立。

  • 到底什么是依赖注入?让我们将这两个词分开来看一看。这里将依赖关系部分转化为两个类之间的关联。例如,类 A 依赖于类 B。现在,让我们看一看第二部分,注入。所有这一切都意味着类 B 将通过 IoC 被注入到类 A 中。

  • 依赖注入可以以向构造函数传递参数的方式发生,或者通过使用 setter 方法 post-construction。由于依赖注入是 Spring 框架的核心部分,所以我将在一个单独的章节中利用很好的例子去解释这一概念。

4、AOP 面向切面编程

  • 面向切面编程 AOP —— Aspect Oriented Programming,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

  • Spring 框架的一个关键组件是面向切面的编程(AOP)框架。面向切面的编程需要把程序逻辑分解成不同的部分称为所谓的关注点。跨一个应用程序的多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。

  • AOP 是 OOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。

  • 在 OOP 中模块化的关键单元是类,而在 AOP 中模块化的关键单元是方面。AOP 帮助你将横切关注点从它们所影响的对象中分离出来,然而依赖注入帮助你将你的应用程序对象从彼此中分离出来。

  • 在 Spring AOP 中业务逻辑仅仅只关注业务本身,将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

  • Spring 框架的 AOP 模块提供了面向方面的程序设计实现,可以定义诸如方法拦截器和切入点等,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于 .Net 属性的方式合并行为信息到代码中。

  • 利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

  • 在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。周边功能在 Spring 的面向切面编程思想里,即被定义为切面。核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能编织在一起。

    • 所谓的 核心业务,比如 登陆,增加数据,删除数据都叫核心业务。
    • 所谓的 周边功能,比如 日志记录,性能统计,安全控制,事务处理,异常处理等等。
  • Spring AOP 模块提供拦截器来拦截一个应用程序,例如,当执行一个方法时,你可以在方法执行之前或之后添加额外的功能。

  • AOP 术语。这些术语并不特定于 Spring,而是与 AOP 有关的。

描述
Aspect 一个模块具有一组提供横切需求的 APIs。例如,一个日志模块为了记录日志将被 AOP 方面调用。应用程序可以拥有任意数量的方面,这取决于需求。
Join point 在你的应用程序中它代表一个点,你可以在插件 AOP 方面。你也能说,它是在实际的应用程序中,其中一个操作将使用 Spring AOP 框架。
Advice 这是实际行动之前或之后执行的方法。这是在程序执行期间通过 Spring AOP 框架实际被调用的代码。
Pointcut 这是一组一个或多个连接点,通知应该被执行。你可以使用表达式或模式指定切入点。
Introduction 引用允许你添加新方法或属性到现有的类中。
Target object 被一个或者多个方面所通知的对象,这个对象永远是一个被代理对象。也称为被通知对象。
Weaving Weaving 把方面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时,类加载时和运行时完成。
  • 通知的类型。Spring 方面可以使用下面提到的五种通知工作。
通知 描述
前置通知 在一个方法执行之前,执行通知。
后置通知 在一个方法执行之后,不考虑其结果,执行通知。
返回后通知 在一个方法执行之后,只有在方法成功完成时,才能执行通知。
抛出异常后通知 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知 在建议方法调用之前和之后,执行通知。
  • 实现自定义方面。Spring 支持 @AspectJ annotation style 的方法和基于模式的方法来实现自定义方面。
方法 描述
XML Schema based 方面是使用常规类以及基于配置的 XML 来实现的。
@AspectJ based @AspectJ 引用一种声明方面的风格作为带有 Java 5 注释的常规 Java 类注释。
  • 配置 AOP

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <!-- applicationContext.xml -->

    <bean name="s" class="com.how2java.service.ProductService">
    </bean>

    <!-- 声明业务对象 -->
    <bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>

    <!-- 声明日志切面 -->
    <aop:config>

    <!-- 指定核心业务功能 -->
    <aop:pointcut id="loggerCutpoint"
    expression=
    "execution(* com.how2java.service.ProductService.*(..)) "/>

    <!-- 指定辅助功能 -->
    <aop:aspect id="logAspect" ref="loggerAspect">
    <aop:around pointcut-ref="loggerCutpoint" method="log"/>
    </aop:aspect>
    </aop:config>
  • 注解方式 AOP

    1
    2
    3
    4
    5
    6
    7
    8
    <!-- applicationContext.xml -->

    <!-- 扫描包 com.how2java.aspect 和 com.how2java.service,定位业务类和切面类 -->
    <context:component-scan base-package="com.how2java.aspect" />
    <context:component-scan base-package="com.how2java.service" />

    <!-- 找到被注解了的切面类,进行切面配置 -->
    <aop:aspectj-autoproxy />
  • 关键字

关键字 介绍
@Aspect 表示这是一个切面
@Component 表示这是一个 bean,由 Spring 进行管理
@Around 表示这个类中的所有方法进行切面操作

5、Spring 容器

  • Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件,这些对象被称为 Spring Beans。

  • 通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过 XML,Java 注释或 Java 代码来表示。

  • Spring 提供了以下两种不同类型的容器

容器 描述
BeanFactory 容器 它是最简单的容器,给 DI 提供了基本的支持,它用 org.springframework.beans.factory.BeanFactory 接口来定义。BeanFactory 或者相关的接口,如 BeanFactoryAwareInitializingBeanDisposableBean,在 Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。
ApplicationContext 容器 该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。
  • ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常不建议使用 BeanFactoryBeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。

6、Spring Bean

  • Spring Bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的。

  • bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

    • 如何创建一个 bean
    • bean 的生命周期的详细信息
    • bean 的依赖关系
  • 上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。

属性 描述
class 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
id / name 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
scope 这个属性指定由特定的 bean 定义创建的对象的作用域。
constructor-arg 它是用来注入依赖关系的。
properties 它是用来注入依赖关系的。
autowiring mode 它是用来注入依赖关系的。
lazy-initialization mode 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
initialization 方法 在 bean 的所有必需的属性被容器设置之后,调用回调方法。
destruction 方法 当包含该 bean 的容器被销毁时,使用回调方法。
  • 下图表达了 Bean 与 Spring 容器之间的关系

6.1 作用域

  • 当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。

  • Spring 框架支持以下五个作用域,分别为 singleton、prototype、request、session 和 global session,5种作用域说明如下所示,

作用域 描述
singleton 在 spring IoC 容器仅存在一个 Bean 实例,Bean 以单例方式存在,默认值
prototype 每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 getBean() 时,相当于执行 newXxxBean()
request 每次 HTTP 请求都会创建一个新的 Bean,该作用域仅适用于 WebApplicationContext 环境
session 同一个 HTTP Session 共享一个 Bean,不同 Session 使用不同的 Bean,仅适用于 WebApplicationContext 环境
global-session 一般用于 Portlet 应用环境,该作用域仅适用于 WebApplicationContext 环境
  • 在 bean 的配置文件中设置作用域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- A bean definition with singleton scope -->
    <bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- A bean definition with singleton scope -->
    <bean id="..." class="..." scope="prototype">
    <!-- collaborators and configuration for this bean go here -->
    </bean>

    </beans>

6.2 生命周期

  • 理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。

  • 尽管还有一些在 Bean 实例化和销毁之间发生的活动,但是有两个重要的生命周期回调方法,它们在 bean 的初始化和销毁的时候是必需的。

  • 为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。

  • Bean 的生命周期可以表达为:Bean 的定义 —— Bean 的初始化 —— Bean 的使用 —— Bean 的销毁

6.3 配置元数据

  • Spring IoC 容器完全由实际编写的配置元数据的格式解耦。有下面三个重要的方法把配置元数据提供给 Spring 容器:

    • 基于 XML 的配置文件
    • 基于注解的配置
    • 基于 Java 的配置
  • 对于基于 XML 的配置,Spring 2.0 以后使用 Schema 的格式,使得不同类型的配置拥有了自己的命名空间,使配置文件更具扩展性。

  • 一个基于 XML 配置文件的例子,这个配置文件中有不同的 bean 定义,包括延迟初始化,初始化方法和销毁方法的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- A simple bean definition -->
    <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- A bean definition with lazy init set on -->
    <bean id="..." class="..." lazy-init="true">
    <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- A bean definition with initialization method -->
    <bean id="..." class="..." init-method="...">
    <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- A bean definition with destruction method -->
    <bean id="..." class="..." destroy-method="...">
    <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

    </beans>
  • 在上述示例中:

    • xmlns="http://www.springframework.org/schema/beans",默认命名空间:它没有空间名,用于 Spring Bean 的定义;

    • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance",xsi 命名空间:这个命名空间用于为每个文档中命名空间指定相应的 Schema 样式文件,是标准组织定义的标准命名空间。

6.4 自动装配

  • Spring 容器可以在不使用 <constructor-arg><property> 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。

  • 自动装配模式。下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用 <bean> 元素的 autowire 属性为一个 bean 定义指定自动装配模式。

模式 描述
no 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。
byName 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
byType 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。
constructor 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
autodetect (3.0版本不支持)Spring 首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。
  • 可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合。

  • 使用 byName

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- Definition for textEditor bean -->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor"
    autowire="byName">
    <property name="name" value="Generic Text Editor" />
    </bean>

    <!-- Definition for spellChecker bean -->
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
    </bean>

    </beans>
  • 使用 byType

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- Definition for textEditor bean -->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor"
    autowire="byType">
    <property name="name" value="Generic Text Editor" />
    </bean>

    <!-- Definition for spellChecker bean -->
    <bean id="SpellChecker" class="com.tutorialspoint.SpellChecker">
    </bean>

    </beans>
  • 自动装配的局限性。当自动装配始终在同一个项目中使用时,它的效果最好。如果通常不使用自动装配,它可能会使开发人员混淆的使用它来连接只有一个或两个 bean 定义。不过,自动装配可以显著减少需要指定的属性或构造器参数,但你应该在使用它们之前考虑到自动装配的局限性和缺点。

限制 描述
重写的可能性 你可以使用总是重写自动装配的 设置来指定依赖关系。
原始数据类型 你不能自动装配所谓的简单类型包括基本类型,字符串和类。
混乱的本质 自动装配不如显式装配精确,所以如果可能的话尽可能使用显式装配。

6.5 基于注解的配置

  • 从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。

  • 在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。

  • 注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它。所以如果你想在 Spring 应用程序中使用的任何注解,可以考虑到下面的配置文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <!-- applicationContext.xml -->

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 告诉 Spring 要用注解的方式进行配置 -->
    <context:annotation-config/>
    <!-- bean definitions go here -->

    <!-- 告诉 Spring,bean 都放在 com.qianchia.pojo 这个包下 -->
    <context:component-scan base-package="com.qianchia.pojo" />

    </beans>
  • 一旦被配置后,就可以开始注解你的代码,表明 Spring 应该自动连接值到属性,方法和构造函数。让我们来看看几个重要的注解,并且了解它们是如何工作的:

注解 描述
@Required 应用于 bean 属性的 setter 方法。
@Autowired 可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。
@Qualifier 通过指定确切的将被连线的 bean,@Autowired@Qualifier 注解可以用来删除混乱。
JSR-250 Annotations Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource@PostConstruct@PreDestroy 注解。
  • @Autowired 注解用法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    // 将 @Autowired 注解应用于构造函数
    public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
    this.customerPreferenceDao = customerPreferenceDao;
    }
    }

    // 将 @Autowired 注解应用于 setter 方法

    public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
    }
    }

    // 将 @Autowired 注解应用于具有任意名称和多个参数的方法

    public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
    this.movieCatalog = movieCatalog;
    this.customerPreferenceDao = customerPreferenceDao;
    }
    }

    // 将 @Autowired 注解应用于字段,或者将其与构造函数混合

    public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    private MovieCatalog movieCatalog;
    }

    // 将 @Autowired 注解添加到需要该类型数组的字段或方法

    public class MovieRecommender {

    @Autowired
    private MovieCatalog[] movieCatalogs;
    }

    public class MovieRecommender {

    private Set<MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
    this.movieCatalogs = movieCatalogs;
    }
    }

    public class MovieRecommender {

    private Map<String, MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
    this.movieCatalogs = movieCatalogs;
    }
    }

7、JDBC

  • 在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等。但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQL 语句,处理异常,处理事务,到最后关闭连接。

  • 所以当从数据库中获取数据时,你所做的是定义连接参数,指定要执行的 SQL 语句,每次迭代完成所需的工作。

  • Spring JDBC 提供了几种方法和数据库中相应的不同的类与接口。

7.1 中央框架类

  • JdbcTemplate 是管理所有数据库通信和异常处理的中央框架类。

    • JdbcTemplate 类执行 SQL 查询、更新语句和存储过程调用,执行迭代结果集和提取返回参数值。它也捕获 JDBC 异常并转换它们到 org.springframework.dao 包中定义的通用类、更多的信息、异常层次结构。

    • JdbcTemplate 类的实例是线程安全配置的。所以你可以配置 JdbcTemplate 的单个实例,然后将这个共享的引用安全地注入到多个 DAOs 中。

    • 使用 JdbcTemplate 类时常见的做法是在你的 Spring 配置文件中配置数据源,然后共享数据源 bean 依赖注入到 DAO 类中,并在数据源的设值函数中创建了 JdbcTemplate。

  • 配置数据源。现在,我们需要提供一个数据源到 JdbcTemplate 中,所以它可以配置本身来获得数据库访问。你可以在 XML 文件中配置数据源,其中一段代码如下所示:

    1
    2
    3
    4
    5
    6
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/TEST"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>
    </bean>

7.2 事务管理

  • 一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行,要么完全不执行。事务管理是一个重要组成部分,RDBMS 面向企业应用程序,以确保数据完整性和一致性。

  • 事务的概念可以描述为具有以下四个关键属性说成是 ACID:

    • 原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。
    • 一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。
    • 隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。
    • 持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。
  • 一个真正的 RDBMS 数据库系统将为每个事务保证所有的四个属性。使用 SQL 发布到数据库中的事务的简单视图如下:

    • 使用 begin transaction 命令开始事务。
    • 使用 SQL 查询语句执行各种删除、更新或插入操作。
    • 如果所有的操作都成功,则执行提交操作,否则回滚所有操作。
  • Spring 框架在不同的底层事务管理 APIs 的顶部提供了一个抽象层。Spring 的事务支持旨在通过添加事务能力到 POJOs 来提供给 EJB 事务一个选择方案。Spring 支持编程式和声明式事务管理。EJBs 需要一个应用程序服务器,但 Spring 事务管理可以在不需要应用程序服务器的情况下实现。

  • 局部事务 vs. 全局事务

    • 局部事务是特定于一个单一的事务资源,如一个 JDBC 连接,而全局事务可以跨多个事务资源事务,如在一个分布式系统中的事务。

    • 局部事务管理在一个集中的计算环境中是有用的,该计算环境中应用程序组件和资源位于一个单位点,而事务管理只涉及到一个运行在一个单一机器中的本地数据管理器。局部事务更容易实现。

    • 全局事务管理需要在分布式计算环境中,所有的资源都分布在多个系统中。在这种情况下事务管理需要同时在局部和全局范围内进行。分布式或全局事务跨多个系统执行,它的执行需要全局事务管理系统和所有相关系统的局部数据管理人员之间的协调。

  • 编程式 vs. 声明式

    • Spring 支持两种类型的事务管理:

      • 编程式事务管理 :这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。
      • 声明式事务管理 :这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。
    • 声明式事务管理比编程式事务管理更可取,尽管它不如编程式事务管理灵活,但它允许你通过代码控制事务。但作为一种横切关注点,声明式事务管理可以使用 AOP 方法进行模块化。Spring 支持使用 Spring AOP 框架的声明式事务管理。

8、Web MVC

  • Spring web MVC 框架提供了模型-视图-控制的体系结构和可以用来开发灵活、松散耦合的 web 应用程序的组件。

  • MVC 模式导致了应用程序的不同方面(输入逻辑、业务逻辑和 UI 逻辑)的分离,同时提供了在这些元素之间的松散耦合。

    • 模型:封装了应用程序数据,并且通常它们由 POJO 组成。
    • 视图:主要用于呈现模型数据,并且通常它生成客户端的浏览器可以解释的 HTML 输出。
    • 控制器:主要用于处理用户请求,并且构建合适的模型并将其传递到视图呈现。
  • Spring Web 模型-视图-控制(MVC)框架是围绕 DispatcherServlet 设计的,DispatcherServlet 用来处理所有的 HTTP 请求和响应。Spring Web MVC DispatcherServlet 的请求处理的工作流程如下图所示:

  • 下面是对应于 DispatcherServlet 传入 HTTP 请求的事件序列:

    • 收到一个 HTTP 请求后,DispatcherServlet 根据 HandlerMapping 来选择并且调用适当的控制器。

    • 控制器接受请求,并基于使用的 GET 或 POST 方法来调用适当的 service 方法。Service 方法将设置基于定义的业务逻辑的模型数据,并返回视图名称到 DispatcherServlet 中。

    • DispatcherServlet 会从 ViewResolver 获取帮助,为请求检取定义视图。

    • 一旦确定视图,DispatcherServlet 将把模型数据传递给视图,最后呈现在浏览器中。

  • 上面所提到的所有组件,即 HandlerMapping、Controller 和 ViewResolver 是 WebApplicationContext 的一部分,而 WebApplicationContext 是带有一些对 web 应用程序必要的额外特性的 ApplicationContext 的扩展。

  • 你需要映射你想让 DispatcherServlet 处理的请求,通过使用在 web.xml 文件中的一个 URL 映射。下面是一个显式声明和映射 HelloWeb DispatcherServlet 的示例:

    • web.xml 文件将被保留在你的应用程序的 WebContent/WEB-INF 目录下。好的,在初始化 HelloWeb DispatcherServlet 时,该框架将尝试加载位于该应用程序的 WebContent/WEB-INF 目录中文件名为 [servlet-name]-servlet.xml 的应用程序内容。在这种情况下,我们的文件将是 HelloWeb-servlet.xml。

    • 接下来,servlet-mapping 标签表明哪些 URLs 将被 DispatcherServlet 处理。这里所有以 .jsp 结束的 HTTP 请求将由 HelloWeb DispatcherServle t处理。

  • 如果你不想使用默认文件名 [servlet-name]-servlet.xml 和默认位置 WebContent/WEB-INF,你可以通过在 web.xml 文件中添加 servlet 监听器 ContextLoaderListener 自定义该文件的名称和位置,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <web-app...>

    ....
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/HelloWeb-servlet.xml</param-value>
    </context-param>
    <listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>
    </web-app>
  • 现在,检查 HelloWeb-servlet.xml 文件的请求配置,该文件位于 web 应用程序的 WebContent/WEB-INF 目录下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.tutorialspoint" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
    </bean>

    </beans>
  • 以下是关于 HelloWeb-servlet.xml 文件的一些要点:

    • [servlet-name]-servlet.xml 文件将用于创建 bean 定义,重新定义在全局范围内具有相同名称的任何已定义的 bean。

    • <context:component-scan> 标签将用于激活 Spring MVC 注释扫描功能,该功能允许使用注释,如 @Controller@RequestMapping 等等。

    • InternalResourceViewResolver 将使用定义的规则来解决视图名称。按照上述定义的规则,一个名称为 hello 的逻辑视图将发送给位于 /WEB-INF/jsp/hello.jsp 中实现的视图。

9、单元测试

  • Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。

  • Spring 支持 JUnit4,可以通过注解方式方便地测试 Spring 程序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

    import com.how2java.pojo.Category;

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class TestSpring {

    @Autowired
    Category c;

    @Test
    public void test(){
    System.out.println(c.getName());
    }
    }
  • 关键字

关键字 介绍
@RunWith 表示这是一个 Spring 的测试类
@ContextConfiguration 定位 Spring 的配置文件
@Autowired 给这个测试类装配Category对象
@Test 测试逻辑

10、Spring MVC

  • Spring MVC 是基于 Spring 的一个 MVC 框架。

  • 主要用于开发 WEB 应用和网络接口,它是 Spring 的一个模块,通过 Dispatcher Servlet, ModelAndView 和 View Resolver,让应用开发变得很容易。

11、Spring Boot

  • Spring Boot 是基于 Spring 的一套快速开发整合包。

  • 包含了包括 Spring 在内的其他东西。它的目的在于实现自动配置,降低项目搭建的复杂度,如需要搭建一个接口服务,通过 Spring Boot,几行代码即可实现。

12、Spring Cloud

  • Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具。

  • Spring Cloud 包含了多个子项目,比如:Spring Cloud Netflix 、Spring Cloud Config、Spring Cloud Stream、Spring Cloud Bus、Spring Cloud Sleuth 等项目。

13、Spring 常见面试题

13.1 Spring

  • 1、问题:你对 Spring 框架的理解(特点)?Spring 框架有哪些模块?

    • Spring 一种用来简化企业应用级开发的一种开源框架。
    • 简化开发:它对常用的 API 做了封装,比如对 JDBC 的封装,使用 Spring JDBC 访问数据库,就不需要考虑如何获取连接和关闭的问题。
    • 解耦:Spring 帮我们管理软件之间的依赖关系,这样对象之间的耦合性就降低了,这样的维护性就得到了提高。
    • 集成其它框架:方便扩展和优化其功能,例如和 Mybatis 的集成等。
    • Spring 框架是按照设计模式精心打造的,这使得我们在开发环境中,能方便的使用框架,不用考虑后台是怎么进行的。
    • Spring 容器是Spring框架中一个核心的模块,用来管理对象的创建,销毁和初始化等操作,以及对象之间的依赖关系等。
    • 目前 Spring 框架已经集合成 20 多个模块:

  • 2、问题:Spring 的优点?

    • 简化开发,解耦,集成其它框架。
    • 低侵入式设计,代码污染级别较低。
    • Spring 的 DI(依赖注入)机制降低了业务对象替换的复杂性,提高了软件之间的解耦。
    • Spring AOP(面向切面编程)支持将一些通用的任务进行集中式的管理,例如:安全,事务,日志等,从而使代码能更好的复用。
  • 3、问题:什么是控制反转(IOC),什么是依赖注入(DI)?

    • IOC:Inversion of control 反转控制,就是对象之间的依赖关系由容器来创建,对象之间的关系本来是由我们开发者自己创建和维护的,在我们使用 Spring 框架后,对象之间的关系由容器来创建和维护,将开发者做的事让容器做,这就是控制反转。BeanFactory 接口是 Spring IOC 容器的核心接口。
    • DI:Dependency Injection 依赖注入,我们在使用 Spring 容器的时候,容器通过调用 set 方法或者是构造器来建立对象之间的依赖关系。通过 IOC 创建对象的时候,可以注入字符串甚至其他对象。比如 DAO 就会注入 session factory。
    • 通常 IOC 和 DI 是紧密结合,一起使用的,控制反转是目标,依赖注入是我们实现控制反转的一种手段。
  • 4、问题:Java 中实现依赖注入的三种方式?

    • 构造器注入
    • set 方法注入
    • 接口注入
  • 5、问题:Spring 容器中如何创建对象?

    • 无参构造创建
    • 静态工厂创建
    • 实例工厂创建
  • 6、问题:Spring 有几种配置方式?

    • 基于 XML 文件的配置:这种配置文件的格式常用 <beans> 开头,然后运用一系列的 bean 定义和专门的应用配置选项组成。Spring XML 配置方式是使用被 Spring 命名空间所支持的一些列 XML 的标签来实现的。
    • 基于注解的配置:可以使用注解的方式来代替 XML 方式的 bean 元素的配置。这就是组件扫描,常用依赖注入的一些注解有:@Controller @Service @Autowired @RequestMapping @RequestParam @ModelAttribute @Cacheable @CacheFlush @Resource @PostConstruct @PreDestroy @Repository @Scope @SessionAttributes @InitBinder @Required @Qualifier。
    • 组件扫描:容器会扫描 base-package 指定的包及其子包下面的所有类,如果该类有一些特定的注解,则纳入容器进行管理。
    • 在类前面添加的一些特定的注解:@Component 通用注解 @Repository 持久层注解 @Service 业务层注解、@Controller 控制层注解。
    • 基于 Java 的配置。
  • 7、问题:Spring Bean 的生命周期?

    • 指 Spring 中 bean 元素被实例化,和被销毁的过程。我们通过 init-method 属性指定初始化方法;通过 destroy-method 方法指定销毁方法。
    • 注意:只有作用域为 Singleton 的时候才会有效。Spring 作为当前 Java 最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。准确的了解 Spring Bean 的生命周期是非常必要的。我们通常使用 ApplicationContext 作为 Spring 容器。这里,我们讲的也是 ApplicationContext 中 Bean 的生命周期。而实际上 BeanFactory 也是差不多的,只不过处理器需要手动注册。
  • 8、问题:解释什么叫延迟加载?

    • 默认情况下,容器启动之后会将所有作用域为单例的 bean 创建好;但是有的业务场景我们并不需要它提前都创建好;
    • 此时,我们可以在 bean 中设置 lzay-init=“true”,这样,当容器启动之后,作用域为单例的 bean,就不在创建。
  • 9、问题:解释什么是自动装配?

    • 就是将一个 Bean 注入到其它的 Bean 的 Property 中,默认情况下,容器不会自动装配,需要我们手动设定。Spring 可以通过向 Bean Factory 中注入的方式来搞定 bean 之间的依赖关系,达到自动装配的目的。
    • 自动装配建议少用,如果要使用,建议使用 ByName。
  • 10、问题:Spring bean 元素的作用域?

    • 当通过 Spring 容器创建一个 Bean 实例的时候,不仅可以完成 bean 实例的实力化,还可以为 bean 指定作用域。Spring bean 元素的支持以下 5 种作用域:
    • Singleton:单例模式,在整个 spring IOC 容器中,使用 singleton 定义的 bean 将只有一个实例。
    • Prototype:多例模式,每次通过容器中的 getBean 方法获取 prototype 定义的 beans 时,都会产生一个新的 bean 的实例。
    • Request:对于每次 Http 请求,使用 request 定义的 bean 都会产生一个新的实例,只有在 web 应用时候,该作用域才会有效。
    • Session:对于每次 Http Session,使用 session 定义的 Bean 都将产生一个新的实例。
    • Globalsession:每个全局的 Http Sesisonn,使用 session 定义的本都将产生一个新的实例。
  • 11、问题:Spring 中的 bean 是线程安全的么?

    • Spring 框架并没有对单例的 bean 进行多线程的封装处理,线程安全问题和并发问题,需要我们开发者自己考虑。
    • 但实际上,大部分的 Spring bean 并没有可变的状态(比如:service 类和 dao 类),所有在某种程度上来说 Spring 单例 bean 是线程安全的。如果 bean 有多种状态的话(比如: View Model 对象),就需要自行考虑线程安全问题。
  • 12、问题:如何在 Spring 中注入一个 Java Collection ?

    • Spring 提供理论四种集合类的配置元素:
    • <list>:该标签用来装配有重复值的 list 值。
    • <set>:该标签用来装配没有重复值的 set 值。
    • <map>:该标签科以用来注入键值对。
    • <props>:该标签用来支持注入键值对和字符串类型键值对。
  • 13、问题:Spring 框架中都用到了哪些设计模式?

    • 代理模式,在 AOP 中被使用最多。
    • 单例模式,在 Spring 配置文件中定义 bean 的时候默认的是单例模式。
    • 工厂模式, BeanFactory 用来创建对象的实例。
    • 模板方法,用来解决重复性代码。
    • 前端控制器,Spring 提供了 DispatcherSerclet 来对请求进行分发。
    • 视图帮助,Spring 提供了一系列的 JSP 标签。
    • 依赖注入,它是惯穿于 BeanFactory/ApplicationContext 接口的核心理念。
  • 14、问题:Spring 中的事件处理?

    • Spring 的核心是 ApplicatonContext,它负责管理 bean 的完整的生命周期。Spring 提供了以下内置事件:ContextRefreshedEvent ContextStartedEvent ContextStoppedEvent ContextClosedEvent RequestHandleEvent。
    • 由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
    • 监听上下文事件
    • 自定义事件
  • 15、问题:Spring AOP(面向切面)编程的原理?

    • AOP 面向切面编程,它是一种思想。
      • 它就是针对业务处理过程中的切面进行提取,以达到优化代码的目的,减少重复代码的目的。
      • 就比如,在编写业务逻辑代码的时候,我们习惯性的都要写:日志记录,事物控制,以及权限控制等,每一个子模块都要写这些代码,代码明显存在重复。
      • 这时候,我们运用面向切面的编程思想,采用横切技术,将代码中重复的部分,不影响主业务逻辑的部分抽取出来,放在某个地方进行集中式的管理,调用。形成日志切面,事物控制切面,权限控制切面。
      • 这样,我们就只需要关系业务的逻辑处理,即提高了工作的效率,又使得代码变的简洁优雅。
      • 这就是面向切面的编程思想,它是面向对象编程思想的一种扩展。
    • AOP 的使用场景:
      • 缓存、权限管理、内容传递、错误处理、懒加载、记录跟踪、优化、校准、调试、持久化、资源池、同步管理、事物控制等。
    • AOP 的相关概念:
      • 切面(Aspect)
      • 连接点 (JoinPoint)
      • 通知(Advice)
      • 切入点(Pointcut)
      • 代理(Proxy)
      • 织入(WeaVing)
    • Spring AOP 的编程原理?
      • 代理机制 JDK 的动态代理:只能用于实现了接口的类产生代理。
      • Cglib 代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强技术,生成当前类的子类对象。
  • 16、问题:解释一下代理模式(Proxy)

    • 代理模式:代理模式就是本该我做的事,我不做,我交给代理人去完成。就比如,我生产了一些产品,我自己不卖,我委托代理商帮我卖,让代理商和顾客打交道,我自己负责主要产品的生产就可以了。代理模式的使用,需要有本类,和代理类,本类和代理类共同实现统一的接口。然后在main中调用就可以了。本类中的业务逻辑一般是不会变动的,在我们需要的时候可以不断的添加代理对象,或者修改代理类来实现业务的变更。
    • 代理模式可以分为:静态代理 优点:可以做到在不修改目标对象功能的前提下,对目标功能扩展 缺点:因为本来和代理类要实现统一的接口,所以会产生很多的代理类,类太多,一旦接口增加方法,目标对象和代理对象都要维护。动态代理(JDK代理/接口代理)代理对象,不需要实现接口,代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象,需要我们指定代理对象/目标对象实现的接口的类型。Cglib代理 特点: 在内存中构建一个子类对象,从而实现对目标对象功能的扩展。
    • 使用场景:修改代码的时候。不用随便去修改别人已经写好的代码,如果需要修改的话,可以通过代理的方式来扩展该方法。隐藏某个类的时候,可以为其提供代理类 当我们要扩展某个类功能的时候,可以使用代理类 当一个类需要对不同的调用者提供不同的调用权限的时候,可以使用代理类来实现。 减少本类代码量的时候。需要提升处理速度的时候。就比如我们在访问某个大型系统的时候,一次生成实例会耗费大量的时间,我们可以采用代理模式,当用来需要的时候才生成实例,这样就能提高访问的速度。

13.2 Spring MVC

  • 1、问题:什么是 Spring MVC ?

    • Spring MVC 是一个基于 MVC 架构的用来简化 web 应用程序开发的应用开发框架,它是 Spring 的一部分,它和 Struts2 一样都属于表现层的框架。
    • MVC(Model 模型 View 视图 Controller 控制器):这是一种软件架构思想,是一种开发模式,将软件划分为三种不同类型的模块,分别是模型,视图,和控制器。
      • 模型:用于封装业务逻辑处理(java 类);
      • 视图:用于数据展现和操作界面(Servlet);
      • 控制器:用于协调视图和模型(jsp);
    • 处理流程:视图将请求发送给控制器,由控制器选择对应的模型来处理;模型将处理结果交给控制器,控制器选择合适的视图来展现处理结果;

  • 2、问题:Spring MVC 的五大组键?

    • 前端控制器(DispatcherServlet)
    • 映射处理器(HandlerMapping)
    • 处理器(Controller)
    • 模型和视图(ModelAndView)
    • 视图解析器(ViewResolver)
  • 3、问题:Spring MVC 的运行原理?

    • 客户端请求提交到 前端控制器;
    • 由 前端控制器 控制器查询一个或多个 映射处理器。
    • 找到处理请求的 处理器,前端控制器 将请求提交到 处理器。
    • 处理器 调用业务逻辑处理后,返回 模型和视图。
    • 前端控制器 查询一个或多个 视图解析器,找到 模型和视图 指定的视图。
    • 视图负责将结果显示到客户。

  • 4、问题:Spring MVC 的控制器是不是单例模式,如果是,有什么问题,怎么解决?

    • 是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能,解决方案是在控制器里面不能写字段。
  • 5、问题:Spring MVC 怎样设定重定向和转发?

    • 在返回值的前面加 ”forword”,就可以实现让结果转发;
    • 在返回值的前面加上 ”redirect”,就可以让返回值重定向。
  • 6、问题:Spring MVC 的优点?

    • 基于 View 框架的无缝集成,采用 IOC 便于测试。
    • 典型的纯 MVC 架构,Struts 是不完全基于 MVC 框架的。
    • 与 tapestry 是纯正的 Servlet 系统。
  • 7、问题:Spring MVC 中控制器的注解一般用哪个,有没有别的注解可以代替?

    • 一般用 @Controller 注解,表示是表现层,不能使用别的注解代替。
  • 8、问题:@RequestMapping 注解用在类上面有什么作用?

    • 用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
  • 9、问题:基于注解的 Spring MVC 的应用编程步骤?

    • Step1:导包 (Spring-webmvc),添加 Spring 配置文件,配置前端控制器 dispatcherServlet。
    • Step2:写 Controller。
    • Step3:写 JSP。
    • Step4:在 Spring 的配置文件里面添加视图解析器、组建扫描、mvc 注解扫描。
  • 10、问题:Spring MVC 如何读取请求参数值?

    • 方式1:通过 request。
    • 方式2:通过 @RequestParam。
    • 方式3:通过 Javabean。
  • 11、问题:Spring MVC 如何向页面传值?

    • 方式1: 绑定数据到 request。
    • 方式2: 返回 ModelandView。
    • 方式3:绑定数据到 ModelMap。
    • 方式4:绑定数据到 Session。
  • 12、问题:系统如何分层?

    • 表现层(UI):数据的展现,操作页面,请求转发。
    • 业务层(服务层):封装业务处理逻辑。
    • 持久层(数据访问层):封装数据访问逻辑。
    • 各层之间的关系:表示层通过接口调用业务层,业务层通过接口调用持久层,这样,当下一层发生变化改变,不影响上一层的数据。 MVC 是一种表现层的架构思想。

  • 13、问题:Spring MVC 如何解决中文乱码问题?

    • 可以使用 Spring MVC 提供的过滤器(CharacterEncodingFilter)来解决;
    • 只需要配置该过滤器就可以,需要注意的是:过滤器的编码设置应该与 jsp 页面保存一致 表单的提交方式设置为 post。
  • 14、问题:Spring MVC 中的拦截器问题?

    • DispatcherServlet 收到请求之后,如果有拦截器,则先执行拦截器的方法,在执行处理器的方法;
    • 注意:过滤器属于Servlet规范,拦截的是 Servlet 容器的调用过程。
    • 拦截器属于 spring 框架,拦截的是 DispatcherServlet 的调用过程
    • 如何写一个拦截器:
      • 1)写一个 java 类,实现 HandlerInterceptor 接口;
      • 2)在接口方法当中,实现处理逻辑;
      • 3)配置拦截器;
      • 4)拦截器还可以设置优先级:依据配置的顺序来执行。
  • 15、问题:Spring MVC 的异常处理?

    • 可以将异常抛给 Spring 框架,由 Spring 框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。
  • 16、问题:Spring MVC 和 Struts2 的异同?

    • Spring MVC 是一个基于 MVC 架构的用来简化 web 应用程序开发的应用开发框架,它是 Spring 的一部分,它和 Struts2 一样都属于表现层的框架。
    • Spring MVC 是典型的纯 MVC 架构,Struts 是不完全基于 MVC 框架的。
文章目录
  1. 1. 前言
  2. 2. 1、Spring
    1. 2.1. 1.1 体系结构
      1. 2.1.1. 1.1.1 核心容器
      2. 2.1.2. 1.1.2 数据访问/集成 层
      3. 2.1.3. 1.1.3 Web 层
      4. 2.1.4. 1.1.4 Test 模块
      5. 2.1.5. 1.1.5 其他 模块
    2. 2.2. 1.2 配置
  3. 3. 2、IOC 反转控制
  4. 4. 3、DI 依赖注入
  5. 5. 4、AOP 面向切面编程
  6. 6. 5、Spring 容器
  7. 7. 6、Spring Bean
    1. 7.1. 6.1 作用域
    2. 7.2. 6.2 生命周期
    3. 7.3. 6.3 配置元数据
    4. 7.4. 6.4 自动装配
    5. 7.5. 6.5 基于注解的配置
  8. 8. 7、JDBC
    1. 8.1. 7.1 中央框架类
    2. 8.2. 7.2 事务管理
  9. 9. 8、Web MVC
  10. 10. 9、单元测试
  11. 11. 10、Spring MVC
  12. 12. 11、Spring Boot
  13. 13. 12、Spring Cloud
  14. 14. 13、Spring 常见面试题
    1. 14.1. 13.1 Spring
    2. 14.2. 13.2 Spring MVC
隐藏目录