Spring简介

什么是spring

Spring架构图
image.png

Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式组成,Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。

• Spring Core核心容器:核心容器提供Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

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

• Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中

• Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

• Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

• Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

• Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring的核心就是控制反转(IoC)和面向切面(AOP),总的来说,Spring是一个分层的Java轻量级框架之前重量级:EJB

注:刚接触spring时会出现很多不好理解的概念

Spring的作用

  • Spring容器主要负责系统需要的对象生命周期的管理ioc di(控制反转,依赖注入,核心作用,解耦和),以及有依赖关系对象的注入最大程度上实现程序的解耦,实现程序的可重用以及系统的扩展和维护;
  • 通过aop的实现集中管理程序共性问题,简化编码和维护,提供了mvc便于程序的分层设计 。

IOC和DI

  • IOC(Inversion of Control)控制反转:说的是创建对象实例的控制权从代码控制剥离到IOC容器控制,实际就是你在xml文件控制,侧重于原理。


  • DI(Dependency Injection)依赖注入:说的是创建对象实例时,为这个对象注入属性值或其它对象实例,侧重于实现。


IOC是什么

IOC—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”。

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IOC是有专门一个容器来创建这些对象,即由IOc容器来控制对象的创建而不再显式地使用new;谁控制谁?当然是IOC容器控制了对象;控制什么?那就是主要控制了外部资源获取和生命周期(不只是对象也包括文件等)。

为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

用图例说明一下,传统程序设计如图1,都是主动去创建相关对象然后再组合起来:


Spring入门 - 图2

图1 传统应用程序结构图


当有了IOC的容器后,在客户端类中不再主动去创建这些对象了,程序的结构图变成如图2所示:

Spring入门 - 图3

图2 有IOC容器后的程序结构图

  • IOC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序


  • IOC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IOC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。


IOC和DI

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

谁依赖于谁:当然是应用程序依赖于IOC容器;
为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源;
谁注入谁:很明显是IOC容器注入应用程序某个对象,应用程序依赖的对象;
注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

谁依赖于谁:当然是应用程序依赖于IOC容器;

为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源;

谁注入谁:很明显是IOC容器注入应用程序某个对象,应用程序依赖的对象;

注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

IOC和DI有什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IOC而言,“依赖注入”明确描述了“被注入对象依赖IOC容器配置依赖对象”。


Spring入门程序

创建maven工程,添加jar包

  1. <br />**通过maven引用:**
    <!-- spring mvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <!-- spring4 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

Spring bean

一个简单的Spring bean

image.png

Spring bean 配置文件

创建Spring配置文件,并声明所有可用的Spring bean。

在resource目录下面创建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:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
              http://www.springframework.org/schema/beans/spring-beans.xsd  
              http://www.springframework.org/schema/mvc  
              http://www.springframework.org/schema/mvc/spring-mvc.xsd  
              http://www.springframework.org/schema/context  
              http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 创建bean -->
    <bean id="person" class="com.hzit.bean.Person">
        <property name="userName" value="张三" />
    </bean>
</beans>

测试代码

public static void main(String[] args) {
        // 加载配置文件
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    Person bean = context.getBean("person", Person.class);
    bean.sayHello();
}

输出结果

image.png

演示减耦合效果

面向对象的概念,是一个很好的设计来打破系统进入一个组可重用的对象。然而,当系统变大,尤其是在Java项目,庞大的对象依赖关系将一直紧密耦合引起对象难以管理或修改。在这种情况下,可以使用Spring框架作为一个核心模块轻松高效地管理所有的对象依赖。

案例:使用不同的语言打招呼


1. 创建好统一的接口SalHello.java,定义打招呼的方法

image.png

2. 分别定义SayChinese.java和SayEnglish.java文件,分别实现打招呼方法

image.png

image.png

3. 定义帮助类SayHelp.java文件,用来统一打印信息

image.png

4. 在applicationContext.xml中配置bean

image.png

5. 测试

image.png

现在,已经实现了松耦合,当需要输出改变时,不必修改任何代码.java文件,只要修改ApplicationContext.xml文件中的ref值,就可以实现输出不同的内容,不修改代码就减少了出错的可能性。

Spring的bean管理

1.Bean实例化的创建

image.png

2.Bean标签的常用属性

属性 作用
id 表示唯一标识
class

表示ID对应类的全路径

| | scope | bean的作用域:

singleton:是默认值 表示单例的意思

prototype:多例的

request:web项目中创建bean对象,存到request域中

session: web项目中创建bean对象,存到session域中

|

Spring依赖注入(DI)

在Spring框架中,依赖注入(DI)的设计模式是用来定义对象彼此间的依赖。
它主要有三种类型:

· Setter方法注入(最多的方式)
· 构造器注入
· 接口注入(很少用)

1.Setter方法注入

这是最流行最简单的DI注入方法,通过设置方法注入依赖。

实体类:
image.png

配置bean文件:

image.png

2.构造函数注入

此DI方法将通过构造函数注入依赖。

Name:对应实体类构造方法的里面的名称
image.png

image.png

setter方法还是构造函数注入?

Spring框架的设置有没有硬性规定,只需要使用适合你的项目需要的类型注入。然而,由于setter方法注入简单,它总是大部分使用场景的选择。

Spring集合 (List,Set,Map,Properties) 实例

下面例子向您展示Spring如何注入值到集合类型(List, Set, Map, and Properties)。 支持4个主要的集合类型:

image.png

<bean id="myList" class="com.hzit.bean.Customer">
        <property name="empList">
            <list>
                <ref bean="emp1" />
                <ref bean="emp2" />
                <ref bean="emp3" />
            </list>
        </property>

        <property name="empSet">
            <set>
                <ref bean="emp1" />
                <ref bean="emp2" />
                <ref bean="emp3" />
            </set>
        </property>

        <property name="empMap">
            <map>
                <entry key="key1" value-ref="emp1" />
                <entry key="key2" value-ref="emp2" />
                <entry key="key3" value-ref="emp3" />
            </map>
        </property>

        <property name="empPer">
            <props>
                <prop key="aa">123</prop>
                <prop key="bb">456</prop>
            </props>

        </property>

    </bean>



    <bean id="emp1" class="com.hzit.bean.Dept">
        <property name="name" value="zhangsan" />
        <property name="pwd" value="123" />
    </bean>
    <bean id="emp2" class="com.hzit.bean.Dept">
        <property name="name" value="lisi" />
        <property name="pwd" value="456" />
    </bean>
    <bean id="emp3" class="com.hzit.bean.Dept">
        <property name="name" value="wangwu" />
        <property name="pwd" value="789" />
    </bean>

Spring注入日期到bean属性

声明一个dateFormat bean,在“customer” Bean,引用 “dateFormat” bean作为一个工厂bean。该工厂方法将调用SimpleDateFormat.parse()自动转换成字符串Date对象。

image.png

使用注解注入的方式

常用的注解

注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired、Resource、Service、Controller、Repository、Component。

Component

标记类是组件,spring扫描注解配置时,会标记这些类要生成bean。

Controller、Service、Repository

分别标记的类是Controller控制层的类,Service服务层的类,Repository数据存储层也就是Dao层的类。

其实上面这三个标签都可以使用Compoent注解来使用

Autowired

表示自动注入属性,可以不写名称,根据类型去自动去查询

image.png

image.png

Resource

属于jdk的注解,通过指定bean名称注入
image.png

spring中使用注解

步骤一: 在applicationContext.xml配置文件中添加命名空间

image.png

<?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.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 

</beans>

步骤二:在beans中添加扫描的标签

<!-- 开启注解扫描  ,如果有多个包可以使用,(逗号)隔开   -->
    <context:component-scan base-package="com.xx" />

步骤三:直接在需要的地方使用相关的注解