SSM系列(一)---Spring IoC 分析
本文主要介绍了 Spring 框架,通过代码演示详细讲述了 Spring IoC 的具体流程。
更多文章欢迎访问我的个人博客–>幻境云图
1. 概述
Spring 是一个开源容器框架,可以接管 web 层,业务层,dao 层,持久层的组件,并且可以配置各种bean,和维护 bean 与 bean 之间的关系。其核心就是控制反转(IoC),和面向切面(AOP),简单的说就是一个分层的轻量级开源框架。
2. Spring 中的 IoC
- IoC:(Inverse of Control )控制反转,容器主动将资源推送给它所管理的组件,组件所做的是选择一种合理的方式接受资源。 - 简单的理解:把创建对象和维护之间的关系的权利由程序中转移到Spring容器的配置文件中。 
- DI : (Dependency Injection) 依赖注入,IoC 的另一种表现方式,组件以一种预先定义好的方式来接受容器注入的资源。 
3. IoC 例子
3.1 xml 配置文件方式
1. 准备 bean 对象
先准备两个简单的实体类 Student 和 Book,需要提供Getter/Setter 和有参数无参构造方法等。
Spring Bean是事物处理组件类和实体类(POJO)对象的总称,Spring Bean 被Spring IoC 容器初始化,装配和管理。
/**
 * @author illusory
 * @version 1.0.0
 * @date 2019/4/18 0018
 */
public class Student {
    private String name;
    private int age;
    private Book book;
    //省略Getter/Setter和构造方法
}
/**
 * @author illusory
 * @version 1.0.0
 * @date 2019/4/18
 */
public class Book {
    private String type;
    private String name;
   //省略Getter/Setter和构造方法
}
2. 将 Bean 类添加到 Spring IoC 容器
将 Bean 类添加到 Spring IoC 容器有三种方式。
- 一种方式是基于XML的配置文件;
- 一种方式是基于注解的配置;
- 一种方式是基于 Java 的配置。
1. Spring Bean 类的配置项
Spring IoC 容器管理 Bean 时,需要了解 Bean 的类名、名称、依赖项、属性、生命周期及作用域等信息。为此,Spring IoC 提供了一系列配置项,用于 Bean 在 IoC 容器中的定义。
- ① class
该配置项是强制项,用于指定创建 Bean 实例的 Bean 类的路径。
- ② name
该配置项是强制项,用于指定 Bean 唯一的标识符,在基于 XML 的配置项中,可以使用 id和或 name 属性来指定 Bean 唯一标识符。
- ③ scope
该配置项是可选项,用于设定创建 Bean 对象的作用域。
- ④ constructor-arg
该配置项是可选项,用于指定通过构造函数注入依赖数据到 Bean。
- ⑤ properties
该配置项是可选项,用于指定通过 set 方法注入依赖数据到 Bean。
- ⑥ autowiring mode
该配置项是可选项,用于指定通过自动依赖方法注入依赖数据到 Bean。
- ⑦ lazy-initialization mode
该配置项是可选项,用于指定 IoC 容器延迟创建 Bean,在用户请求时创建 Bean,而不要在启动时就创建 Bean。
- ⑧ initialization
该配置项是可选项,用于指定 IoC 容器完成 Bean 必要的创建后,调用 Bean 类提供的回调方法对 Bean 实例进一步处理。
- ⑨ destruction
该配置项是可选项,用于指定 IoC 容器在销毁 Bean 时,调用 Bean 类提供的回调方法。
2. Spring xml 配置文件
下面主要介绍基于XML的配置方式,基于注解和基于Java的配置放在后面进行讨论,放在后面讨论的原因是一些其它重要的Spring概念还需要掌握。
<?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的配置文件 -->
    <bean id="student" class="spring.Student">
        <property name="name" value="illusory"></property>
        <property name="age" value="23"></property>
        <property name="book" ref="book"></property>
    </bean>
    <bean id="book" class="spring.Book">
        <property name="name" value="think in java"></property>
        <property name="type" value="CS"></property>
    </bean>
</beans>
3.2 注解方式
使用注解需要在xml配置文件中开启组件扫描
    <!--配置组件扫描-->
    <context:component-scan base-package="spring"/>
1.定义 bean
定义一个 bean 实体类或组件
@Component(value = "book")
public class Book {
    private String type;
    private String name;
   //省略Getter/Setter和构造方法
}
2. 配置 bean
- 基本配置
@Component(value = "book")
public class Book {
    private String type;
    private String name;
   //省略Getter/Setter和构造方法
}
其中@Component(value = "book")相当于<bean id="book" class="spring.Book">
Bean实例的名称默认是Bean类的首字母小写,其他部分不变
- 属性注入
普通类型注入: @Value(value = "illusory")
引用类型注入: @Autowired/@Resources(name="")
@Component(value = "student")
public class Student {
    @Value(value = "illusory")
    private String name;
    @Value(value = "23")
    private int age;
    @Autowired
    private Book book;
}
@Component(value = "book")
public class Book {
    @Value(value = "defaultType")
    private String type;
    @Value(value = "defaultName")
    private String name;
}
3. 获取 bean
    public static void main(String[] args) {
        // 根据配置文件创建 IoC 容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中获取 bean 实例
        Student student = (Student) ac.getBean("student");
        // 使用bean
        System.out.println(student.getName());
        //成功打印出 illusory
    }
3.3 测试
/**
 * @author illusory
 * @version 1.0.0
 * @date 2019/4/18
 */
public class SpringTest {
    public static void main(String[] args) {
        // 根据配置文件创建 IoC 容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中获取 bean 实例 这里的名称就是配置文件中的id="student"
        Student student = (Student) ac.getBean("student");
        // 使用bean
        System.out.println(student.getName());
        //成功打印出 illusory
    }
}
4. 简要分析
4.1 创建Spring IoC 容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext .xml")
执行这句代码时 Spring 容器对象被创建,同时 applicationContext .xml中配置的 bean 就会被创建到内存中。
4.2 Bean注入
Bean 注入的方式有两种;
- 一种是在XML中配置,此时分别有属性注入、构造函数注入和工厂方法注入;
- 另一种则是使用注解的方式注入:@Autowired、@Resource、@Required。
1. 在xml文件中配置依赖注入
- 属性注入
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。
<bean id="book" class="spring.Book">
        <property name="name" value="think in java"></property>
        <property name="type" value="CS"></property>
</bean>
例子中的这个就是属性注入。
- 构造方法注入
使用构造函数注入的前提是 Bean必须提供带参数的构造函数。
    <bean id="book" class="spring.Book">
        <constructor-arg name="name" value="think in java"></constructor-arg>
        <constructor-arg name="type" value="CS"></constructor-arg>
    </bean>
- 工厂方法注入
有时候 bean 对象不能直接 new,只能通过工厂方法创建。
/**
 * @author illusory
 * @version 1.0.0
 * @date 2019/4/18 0018
 */
public class BookFactory {
    //非静态方法
    public Book createBook() {
        Book book = new Book();
        book.setName("图解HTTP");
        book.setType("HTTP");
        return book;
    }
    //静态方法
    public static Book createBookStatic() {
        Book book = new Book();
        book.setName("大话数据结构");
        book.setType("数据结构");
        return book;
    }
}
非静态方法:必须实例化工厂类(factory-bean)后才能调用工厂方法
 <bean id="bookFactory" class="spring.BookFactory"></bean>
 <bean id="book" class="spring.Book" factory-bean="bookFactory" factory-method="createBook"></bean>
静态方法:不用实例化工厂类(factory-bean)后才能调用工厂方法
<bean id="book" class="spring.Book" factory-method="createBookStatic"></bean>
4.3 获取 bean 实例
接着通过从 Spring 容器中根据名字获取对应的 bean 。
Student student = (Student) ac.getBean("student");
5. 小结
5.1 大致流程
- 1.定义bean:定义一个 bean 实体类或组件 
- 2.配置 bean - 基本配置 xml 配置文件中注册这个 bean
- 属性注入 xml 配置文件中为这个 bean 注入属性- XML中配置 : 属性注入、构造方法注入、工厂方法注入
- 注解方式 : @Autowired、@Resource、@Required
 
- XML中配置 : 
 
- 3.获取 bean 实例:根据 name(即配置文件中的 bean id) 从 Spring 容器中获取 bean 实例 
5.2 具体代码
1. 定义 bean
定义一个 bean 实体类或组件
public class Book {
    private String type;
    private String name;
   //省略Getter/Setter和构造方法
}
2. 配置 bean
- 基本配置
    <bean id="book" class="spring.Book">
    </bean>
- 属性注入
    <bean id="book" class="spring.Book">
        <property name="name" value="think in java"></property>
        <property name="type" value="CS"></property>
    </bean>
3. 获取 bean
 // 根据配置文件创建 IoC 容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 从容器中获取 bean 实例
        Student student = (Student) ac.getBean("student");
6. 参考
https://blog.csdn.net/u010648555/article/details/76299467
https://www.cnblogs.com/_popc/p/3972212.html
https://www.cnblogs.com/wnlja/p/3907836.html