Spring核心容器(一) | IoC和DI快速入门

Core Container核心容器

核心概念

一个概念的提出往往是为了解决一些问题的, 那么我们现在编写的代码存在什么样的问题呢? 我们看下面一段代码:

有如下一段业务层的代码: 创建一个数据层BookDaoImpl2的对象, 并调用该对象的save方法

public class BookServiceImpl implements BookService {
    
    
    private BookDao bookDao = new BookDaoImpl1();
    public void save() {
    
    
        bookDao.save();
    }
}

数据层实现代码:

public class BookDaoImpl implements BookDao {
    
    
		public void save() {
    
    
       	System.out.println("book dao save ...");
		}
}

如果我们此时想要换一套如下代码的全新数据层的实现, 那么业务层中的new BookDaoImpl1()需要换成new BookDaoImpl2()

public class BookDaoImpl2 implements BookDao {
    
    
		public void save() {
    
    
        System.out.println("book dao save ...2");
    }
}

现在书写代码带来的问题就是, 耦合度偏高; 而我们程序的书写追求的是低耦合

解决方案:

使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象, 而这种思想就是IoC(Inversion of Control) 控制反转

IoC (Inversion of Control) 控制反转:

使用对象时,由主动new产生对象, 转换为由外部提供对象; 对象的创建控制权由程序转移到外部,这种思想称为控制反转

Spring技术对IoC思想进行了实现:

Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的 “外部”

IoC容器负责对象的创建、初始化等一系列工作,被IoC容器创建或管理的对象在IoC容器中统称为Bean

DI (Dependency Injection) 依赖注入:

在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入;

例如某一个bean需要作为对象给其他的bean使用

最终目标: 充分解耦:

步骤一: 使用IoC容器管理bean(IoC)

步骤二: 在IoC容器内将有依赖关系的bean进行关系绑定(DI)

最新效果: 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

创建容器

创建容器的方式:

方式一:类路径加载配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

方式二:文件绝对路径路径加载配置文件

ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext.xml");

不管使用哪种方式, 都可以加载多个配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml", "bean2.xml");

容器类层次结构图如下:

BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载

ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载

ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能

ApplicationContext接口常用初始化类

  • ClassPathXmlApplicationContext
  • FileSystemXmlApplicationContext

在这里插入图片描述

Ioc快速入门

我们通过案例快速入门IoC(XML版), 案例的准备工作如下

案例的目录结构如下

在这里插入图片描述

BookDao接口和BookDaoImpl实现类代码如下

public interface BookDao {
    
    
    void save();
}
public class BookDaoImpl implements BookDao {
    
    
    public void save() {
    
    
        System.out.println("book dao save...");
    }
}

BookService接口和BookServiceImpl实现类代码如下

public interface BookService {
    
    
    void save();
}
public class BookServiceImpl implements BookService {
    
    
    private BookDao bookDao = new BookDaoImpl();
    
    public void save() {
    
    
        System.out.println("book service save");
      	// 调用BookDaoImpl中的方法
        bookDao.save();
    }
}

有一个App类调用BookServiceImpl的实例方法

public class App {
    
    
    public static void main(String[] args) {
    
    
        BookService bookService = new BookServiceImpl();
        bookService.save();
    }
}

IoC入门案例思路分析:

导入使用Spring的依赖坐标(pom.xml)

此案例中我们需要IoC管理Service和Dao

通过配置方式, 将被管理的对象告知IoC容器

被管理的对象交给IoC容器后,我们可以通过接口获取到IoC容器

IoC容器得到后,通过接口方法从容器中获取bean

IoC入门案例实现(XML版):

在pom.xml文件中导入Spring坐标

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

在resource文件夹中创建一个Spring的配置文件applicationContext.xml,配置对应类作为Spring管理的bean

  • 注意: bean定义时id属性在同一个上下文中不能重复
<?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-->
    <!--id属性表示给bean取名字-->
    <!--class属性表示给bean定类型-->
    <bean id="bookService" class="com.chenyq.service.impl.BookServiceImpl"/>

</beans>

初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean

public class App {
    
    
    public static void main(String[] args) {
    
    
        // 获取IoC容器, 参数是Spring配置文件名
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean, 通过getbean方法
        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }
}

DI快速入门

在上面IoC案例中, 我们业务层其实还是没有解耦的:

在BookServiceImpl类的save方法中还是使用的new BookDao的形式创建的对象

DI入门案例思路分析(XML版):

DI是基于IoC管理bean

Service中使用new创建的Dao对象的形式不保留, 需要通过DI解耦

Service中需要的Dao对象, 需要通过提供方法的方式, 让Dao对象进入到Service中

Service与Dao间的关系需要 描述通过配置文件描述

DI入门案例实现(XML版):

删除使用new的形式创建对象的代码

public class BookServiceImpl implements BookService {
    
    
  	// private BookDao bookDao = new BookDaoImpl();
  	private BookDao bookDao; // 不使用new形式创建对象
  
  	public void save() {
    
    
      	bookDao.save();
    }
}

提供依赖对象对应的setter方法, 该setter方法是容器调用的

public class BookServiceImpl implements BookService {
    
    
    private BookDao bookDao;

    public void save() {
    
    
        System.out.println("book service save");
        bookDao.save();
    }

    // 提供setter方法
    public void setBookDao(BookDao bookDao) {
    
    
        this.bookDao = bookDao;
    }
}

配置service与dao之间的关系

<?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-->
    <!--id属性表示给bean取名字-->
    <!--class属性表示给bean定类型-->
    <bean id="bookDao" class="com.chenyq.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.chenyq.service.impl.BookServiceImpl">
        <!--配置Service和Dao的关系, property标签标识当前bean的属性-->
        <!--name属性表示配置当前bean的哪一个属性-->
        <!--ref属性表示配置参照哪一个bean-->
        <property name="bookDao" ref="bookDao"/>
    </bean>

</beans>

猜你喜欢

转载自blog.csdn.net/m0_71485750/article/details/127947624