Spring IOC总结

时间:2021-07-07 01:27:21


简介

  1. Spring框架是由于软件的开发的复杂而创建的,目的就是解决软件开发的复杂性问题,他是基于在JavaBean的基础上来完成之前只能由EJB完成的事情,替代了JDBC的框架(MyBits);给软件行业带来了春天;
  2. Spring框架使用与任何的Java应用,是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架;
  3. Spring使得Java EE的开发更加的容易了,他与Struts,Hibernate等单层框架不同,他是致力于提供一个以统一的,高效的方式构造整个应用,并且可以将单层框架以最佳的方式组合在一起,建立一个连贯的体系;可以为POJO(Plain Ordinary Java Object)对象提供企业级的服务。
  4. Spring是在2002年,来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,2003年,Spring框架以interface21框架为基础,重新设计.发布了1.0正式版;

Spring官网:  https://spring.io/

Spring的下载: https://spring.io/projects/spring-framework#learn

版本介绍:

我们在下载软件会遇到诸如release,stable,alpha,beta,pre,current,eval,rc,snapshot等版本,程序猿下载插件时尤为常见,介绍几个版本:

  1. snapshot(快照),也即开发版,我们创建maven项目时,编辑器会自动给我们填入 1.0-SNAPSHOT版本,也就是1.0开发版,这个版本不能使用,因为该版本处于开发的过程,所以运行时会不时地更新,导致功能变化,正式环境中不得使用snapshot版本的库;
  2. alpha,内部测试版,来源于字母α,是比较早的版本,主要是给开发人员和测试人员测试和找BUG用的,不建议使用;
  3. beta,公开测试版,来源于字母β,这是比alpha进一步的版本,面向公众测试,但是不建议使用
  4. pre,这个和alpha版本类似,有时还会细分为M1,M2版本,不建议使用;
  5. RC(Release Candidate) 顾名思义么 ! 用在软件上就是候选版本。系统平台上就是发行候选版本;
  6. GA(General Availability)正式发布的版本,在国外都是用GA来说明release版本的;
  7. release,发行版,这是release的中文意思,也就是官方推荐使用的版本;
  8. stable,稳定版,这个版本相比于测试版更加稳定,去除了测试版许多的bug,完善了一些功能,建议使用;
  9. current,最新版,但是不一定是稳定版本,需要看一下是否还有release或者stable等版本;
  10. eval,评估版。可能会有一个月或者固定时间的使用期限;

SpringGithub地址:https://github.com/spring-projects/spring-framework

Spring官网下载地址https://repo.spring.io/release/org/springframework/spring/

Spring的优点:

  1. Spring是一个轻量级的框架,非入侵式框架;(使用时没有其他的依赖,也不需要导入其他的包);
  2. 控制反转(IOC)和面向切面(AOP)的容器框架;
  3. Spring对事务的支持;
  4. Spring对框架的支持,不需要任何成本就可以引入其他的框架

Spring的框架

Spring IOC总结

Spring的架构:MVC架构

Spring框架是一个分层的架构,由7个定义良好的模块组成.Spring模块构建在核心容器上,核心容器定义了创建、配置和管理bean的方式;

Spring IOC总结

从下向上看spring的主要内容:

Test:Spring支持Junit单元测试

核心容器(IOC):Bean(Bean工厂,创建对象)、Core(一切的基础)、Context(上下文)、SpEL(Spring的表达式语言);

AOP:AOP、Aspects

对数据访问的支持:JDBC、ORM、Transaction、JMS(java邮件服务)

对web的支持:Spring MVC

组成Spring的框架的每个模块(或组件)都可以单独的存在,或者其他的一个或多个模块联合实现,每个模块的功能如下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
  • Spring 上下文: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 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。

Spring组件:

Spring IOC总结

SpringBoot和Spring Cloud

Spring IOC总结

SpringBoot:一款可以快速构建Spring应用的脚手架;约定大于配置,承上启下;

  1. Spring Boot是构建所有基于Spring的应用程序的起点。
  2. Spring Boot旨在尽可能快地启动和运行,只需最少的Spring前端配置。

Spring Cloud:基于SpringBoot实现的;他是一个生态圈;通过实施经过验证的模式,为微服务带来弹性,可靠性和协调,从而简化了分布式微服务式架构。

IOC

IOC----inversion of control控制反转

  1. 控制反转模式(也称作依赖性介入)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器 (在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。
  2. 在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。下表列出了 IOC 的一个实现模式。

 IOC的别名:依赖注入(DI)

2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中

所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦(微服务)。

引入一个图来方便理解:

Spring IOC总结

IOC让程序的耦合性大大降低,方便了模块的独立;(低耦合高内聚)

实例:

HelloSpring

Spring IOC总结

  • 1.导入jar包
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.9.RELEASE</version>
</dependency>
  • 创建实体类
package com.zhang.pojo;

public class HelloSpring {
    private String name;
    public HelloSpring() {
    }

    public HelloSpring(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void show(){
        System.out.println("Hello,"+name);
    }

    @Override
    public String toString() {
        return "Hello{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • 创建Spring的配置文件  bean.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean 就是一个java对象,有spring创建和管理-->
    <bean  class="com.zhang.pojo.HelloSpring">
    <property name="name" value="Spring"/>
</bean>
</beans>
  • 编写测试类;
package SpringTest;

import com.zhang.pojo.HelloSpring;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
    @Test
    public void tast(){
        //解析bean.xml配置文件,生产管理相同的bean对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    //通过bean得到这个对象的实体
       HelloSpring hello = (HelloSpring) context.getBean("hello");
        hello.show();
    }
}

以上代码编译运行的结果如下图所示:

Spring IOC总结

通过这个测试我们可以看出在这个测试中,

  1. Hello对象就是由Spring创建的,而Hello对象的属性的值是由Spring容器创建的;
  2. bean.xml 配置文件是用来管理Java对象;
  3. 而Spring就像一个容器一样,存放了许多的对象;

但是如何将bean.xml文件转换成为对象的,其实主要就是经过了以下两步:

  1. 解析配置文件,
  2. 通过反射创建对象并且设置值;

控制反转

控制:谁来控制对象的创建,传统应用程序是由程序本身控制创建的,但是在使用Spring之后,对象就由Spring创建;

反转:程序本身不创建对象,变成了被动的接收对象;

依赖注入:就是利用set的方法进行的注入;IOC就是一种编程思想,有一种主动的编程变成了被动的接收;

所谓的IOC就是:由Spring创建,管理,和装配对象;

IOC创建对象的方式

我们平时创建对象的方式就是:有参构造,无参构造;

但是在Spring中又是如何实现的呢?

  • 创建实体类
package com.zhang.pojo;

public class User {
    private String name;
    private String sex;
    private int age;

    public User() {
        System.out.println("User的无参构造");
    }

    public User(String name) {
        System.out.println("User的有参构造");
        this.name = name;
    }

    public User(String name, int age) {
        System.out.println("User的有参构造2");
        this.name = name;
        this.age = age;
    }

    public User(String name, String sex, int age) {
        System.out.println("User的有参构造3");
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public void setName(String name) {
        System.out.println(name+":"+System.currentTimeMillis());
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 编写配置文件。beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<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.xsd">
<!--Spring 的配置文件-->
<!--bean 代表一个对象-->
<!--alias  别名-->

    <bean  class="com.zhang.pojo.User">
        <property name="name" value="user"/>
    </bean>

    <!--使用构造器的参数下标进行赋值-->
<bean  class="com.zhang.pojo.User">
    <constructor-arg index="0" value="zhang"/>
    <constructor-arg index="1" value="18"/>
</bean>

    <!--使用名字进行赋值-->
    <bean  class="com.zhang.pojo.User">
        <constructor-arg name="name" value="zhang3"/>
        <constructor-arg name="age" value="8"/>
    </bean>

    <!--使用类型进行赋值-->
<bean  class="com.zhang.pojo.User">
    <constructor-arg type="java.lang.String" value="zhang4"/>
    <!--<constructor-arg type="java.lang.Integer" value="16"/>-->
    <!--<constructor-arg type="java.lang.String" value="男"/>-->
</bean>

</beans>
  • 测试类
package com.zhang;

import com.zhang.pojo.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.toString();
    }
    @Test
    public void test2(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user4");
        System.out.println(user);
    }

}

 以上代码编译运行的结果如下:

Spring IOC总结

使用构造器参数设置下标进行赋值

Spring IOC总结

使用名字进行赋值 

Spring IOC总结

使用类型进行赋值 

Spring IOC总结

从上面的运行结果来看,当用类型进行赋值是,方法必须要保持一致,否则就会报错;所以一般不推荐使用,使用最多的是通过参数名进行赋值;

IOC创建对象时必须要有一个无参构造方法;