学习目的和要求
本文主要介绍Spring IoC的基本概念,Spring IoC容器以及依赖注入的类型等内容。通过本文的学习,读者能够了解Spring IoC容器,掌握Spring IoC的基本概念以及依赖注入的类型。
(1)Spring IoC的基本概念。
(2)Spring IoC容器。
(3)依赖注入的类型。
IoC(控制反转)是Spring框架的基础,也是Spring框架的核心理念,本章将介绍IoC基本概念、容器以及依赖注入的类型等内容。
1.1 Spring IoC基本概念
控制反转(Inversion of Control,IoC)是一个比较抽象的概念,是Spring框架的核心,用来消减计算机程序的耦合问题。依赖注入(Dependency Injection,DI)是IoC的另外一种说法,只是从不同的角度描述相同的概念。生活小实例说明:
1. 你想吃汉堡,以前想的是自己做(new)一个,但是可能制作太繁琐了,可能做得不好。
2. 现在不是有外卖商家了嘛,你只要下单,商家给你做各种各样的汉堡。
3. 你只要下单,就会按照你的要求制作汉堡。你没有做汉堡但是你有了一个汉堡。
这就是控制反转的含义:把制作汉堡的主动权交给商家。
传统编程的思想:调用者通常会采用“new”一个被调用者的代码方式来创建对象。这种方式会增加调用者和被调用者之间的耦合性,不利于后期代码的升级与维护。
当Spring框架出现后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring容器负责控制程序之间的关系,而不是调用者的程序代码直接控制。这样控制权调用转移到Spring容器,控制权发生了反转。这就是Spring的控制反转。
综上:控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。
1.2 Spring IoC容器
实现控制反转的是Spring IoC容器。Spring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口。
1.2.1 BeanFactory
在创建BeanFactory实例时需要提供XML文件的绝对路径
import com.kuang.dao.TestDao;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
public class Test {
public static void main(String[] args) {
// 初始化Spring容器,加载配置文件
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D:\\1-bian cheng xue xi\\JAVA\\spring-study\\spring-02-hellospring\\src\\main\\resources\\applicationContext.xml"))
// 通过容器获得test实例
TestDao testDao = (TestDao)beanFactory.getBean("test");
testDao.sayHello();
}
}
注意:使用BeanFactory实例加载Spring配置文件在实际开发中并不多见!!!了解即可
1.2.2 ApplicationContext
ApplicationContext是BeanFactory的子接口,也称为应用上下文,
有三种方法:
(1)通过ClassPathXmlApplicationContext创建
ClassPathXmlApplicationContext将从类路径目录中寻找指定的xml配置文件。
import com.kuang.dao.TestDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// 初始化Spring容器ApplicationContext,加载配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过容器获取test实例
TestDao test = (TestDao)context.getBean("test");
test.sayHello();
}
}
(2)通过FileSystemXmlApplicationContext创建
FileSystemXmlApplicationContext将从指定文件的绝对路径寻找XML配置文件。找到并装载完成ApplicationContext的实例化工作。(一般不推荐使用)
(3)通过Web服务器实例化ApplicationContext容器
在web.xml中添加如下代码即可。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<!--加载src目录下的applicationContext.xml文件-->
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
<!--指定以ContextLocationListener方式启动Spring容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
1.3 依赖注入的类型
Spring框架的依赖注入通常有两种实现方式,一种是使用构造方法注入,另一种是使用属性的Setter注入。
1.3.1 使用构造方法注入
文件目录
(1)TestDao接口的代码如下:
package com.kuang.dao;
public interface TestDIDao {
public void sayHello();
}
(2)TestDIDaoImpl实现类代码如下:
package com.kuang.dao;
public class TestDIDaoImpl implements TestDIDao {
public void sayHello() {
System.out.println("hello spring studty");
}
}
(3)创建service包,TestDIService接口代码如下:
package com.kuang.service;
public interface TestDIService {
public void sayHello();
}
(4)TestDIServiceImpl实现类代码如下:
package com.kuang.service;
import com.kuang.dao.TestDIDao;
public class TestDIServiceImpl implements TestDIService{
private TestDIDao testDIDao;
// 构造方法,用于实现依赖注入接口对象testDIDao
public TestDIServiceImpl(TestDIDao testDIDao){
super();
this.testDIDao = testDIDao;
}
public void sayHello() {
testDIDao.sayHello();
}
}
(5)核心配置文件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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--将指定类TestDIDaoImpl配置给Spring,让Spring创建其实例-->
<bean id="myTestDIDao" class="com.kuang.dao.TestDIDaoImpl"/>
<!--使用构造方法注入-->
<bean id="testDIService" class="com.kuang.service.TestDIServiceImpl">
<!--将myTestDIDao注入到TestDIServiceImpl类的属性testDIDao属性上-->
<constructor-arg index="0" ref="myTestDIDao"/>
</bean>
</beans>
(6)测试类Test
import com.kuang.service.TestDIService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// 初始化spring容器applicationContext,加载配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过容器获取testDIService实例,测试构造方法注入
TestDIService testDIService = (TestDIService)context.getBean("testDIService");
testDIService.sayHello();
}
}
1.3.2 使用属性的setter方法注入
注意:主流的注入方式
(1)创建接口实现类TestDIServiceImpl1
package com.kuang.service;
import com.kuang.dao.TestDIDao;
public class TestDIServiceImpl1 implements TestDIService {
private TestDIDao testDIDao;
// 添加testDIDao属性的setter方法,用于实现依赖注入
public void setTestDIDao(TestDIDao testDIDao){
this.testDIDao = testDIDao;
}
public void sayHello() {
testDIDao.sayHello();
System.out.println("setter注入");
}
}
(2)在applicationContext.xml中将TestDIServiceImpl1实现类托管给Spring
<!--使用setter注入-->
<bean id="testDIService1" class="com.kuang.service.TestDIServiceImpl1">
<!--调用TestDIServiceImpl类的setter方法,将myTestDIDao注入到TestDIServiceImpl类的属性testDIDao-->
<property name="testDIDao" ref="myTestDIDao"/>
</bean>
全部代码:
<?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">
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
<!--将指定类TestDIDaoImpl配置给Spring,让Spring创建其实例-->
<bean id="myTestDIDao" class="com.kuang.dao.TestDIDaoImpl"/>
<!--使用构造方法注入-->
<bean id="testDIService" class="com.kuang.service.TestDIServiceImpl">
<!--将myTestDIDao注入到TestDIServiceImpl类的属性testDIDao属性上-->
<constructor-arg index="0" ref="myTestDIDao"/>
</bean>
<!--使用setter注入-->
<bean id="testDIService1" class="com.kuang.service.TestDIServiceImpl1">
<!--调用TestDIServiceImpl类的setter方法,将myTestDIDao注入到TestDIServiceImpl类的属性testDIDao-->
<property name="testDIDao" ref="myTestDIDao"/>
</bean>
</beans>
(3)测试类
import com.kuang.service.TestDIService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main(String[] args) {
// 初始化spring容器applicationContext,加载配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TestDIService testDIService = (TestDIService)context.getBean("testDIService1");
testDIService.sayHello();
}
}