1.创建项目

要想使用Spring IOC进行程序的解耦,我们首先要将项目的环境还原到耦合时期,也就是第三节刚开始我们创建的项目目录:

└── com
    └── eastnotes
        ├── dao
        │   ├── AccountDao.java
        │   └── impl
        │       └── AccountDaoImpl.java
        ├── service
        │   ├── AccountService.java
        │   └── impl
        │       └── AccountServiceImpl.java
        └── ui
            └── Client.java

2.导入依赖

然后,在Maven工程的pom.xml配置文件中导入Spring依赖,这是Spring的应用上下文包,它的作用是负责Bean对象的创建和组装。

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

Spring自带了多种应用上下文的实现,它们之间主要的区别仅仅在于如何加载配置。主要5种如下:

  • AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文。
  • AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
  • ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
  • FileSystemXmlApplicationContext:从文件系统下的一个或多个XML配置文件中加载上下文定义。
  • XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。

3.创建配置文件

在Maven工程的src > main > resources目录下创建IOC的配置文件,将其命名为bean.xml,然后在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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

4.创建对象配置

为了能让Spring创建并管理我们的Bean对象,我们需要为Spring指定被创建对象的id和全限定类名,于是在刚创建的bean.xml文件中的beans标签内配置这两个属性:

<bean id="accountDao" class="com.eastnotes.dao.impl.AccountDaoImpl"></bean>

<bean id="accountService" class="com.eastnotes.service.impl.AccountServiceImpl"></bean>

配置完成之后,Spring会自动解析这个配置文件,拿到Bean的全限定类名,然后通过反射创建对象,然后再给这个对象贴上唯一的id标签。接下来,我们要做的就是把这个容器中的对象取出来。

5.取出Bean对象

取出Bean对象需要两个步骤:

  • 获取Spring Ioc核心容器,它是一个对象,相当于我们在工厂类中的Map对象,它的全称是ApplicationContext
  • 根据id获取对象

下面是具体的代码:

package com.eastnotes.ui;

import com.eastnotes.dao.AccountDao;
import com.eastnotes.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 模拟一个表现层,用于调业务层
 */
public class Client {
    /**
     * 获取Spring Ioc容器对象,并根据id获取对象
     * @param args
     */
    public static void main(String[] args) {
        //1.通过读取类路径下的配置文件,获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

        //2.获取AccountService对象,手动类型转换(因为本来获取的是Object)
        AccountService as = (AccountService) ac.getBean("accountService");

        //3.获取AccountDao对象,自动类型转换(传入对应类的字节码就行)
        AccountDao adao = ac.getBean("accountDao",AccountDao.class);

        //4.输出验证
        System.out.println(as);
        System.out.println(adao);
    }
}

成功输出对象的内存地址:

com.eastnotes.service.impl.AccountServiceImpl@62e136d3
com.eastnotes.dao.impl.AccountDaoImpl@c8e4bb0

6.总结

可以看到,总体的原理和使用工厂设计模式是一样的,只不过,读取配置文件、创建对象、将对象存入map中的步骤都让Spring自己完成了。而我们只需要获取容器,然后根据id获取对象就可以了。

当然,这个例子做的还不完善,比如说AccountService类中其实还存在着耦合,这里需要依赖注入进行解耦,另外,我们为什么要使用ClassPathXmlApplicationContext这个实现类而不是用别的?有关这两个问题的答案,在后续笔记中会解释的。