【Spring学习随笔】2. Spring IoC
2. Spring IoC
2.1 Spring IoC的基本概念
控制反转(Inversion of Control,IoC)是Spring框架的核心,用来消减计算机程序的偶合问题。
依赖注入(Dependency Injection,DI)是IoC的另外一种说法,只是从不同的角度描述相同的概念。
当Spring框架出现后,对象的实例不再由调用者来创建,而是由Spring容器来创建。Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由调用者转移到Spring容器,控制权发生了反转,这就是Spring的控制反转。
从Spring容器角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例,这就是Spring的依赖注入。
综上所述,控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。
2.2 Spring IoC容器
2.2.1 BeanFactory
BeanFactory由org.springframework.beans.factory.BeanFactory接口定义,他提供了完整的IoC服务支持,是一个管理Bean的工厂,主要负责初始化各种Bean。BeanFactory接口有多个实现类,其中比较常用的是org.springframework.beans.factory.xml.XmlBeanFactory。
在创建BeanFactory实例时需要提供XML文件的绝对路径。下面是main方法中的一个示例代码:
public static void main(String[] args) {
//初始化Spring容器,加载配置文件
BeanFactory beanFac = new XmlBeanFactory(
new FileSystemResource("D:\eclipse-workspace\ch1\src\
applicationContext.xml")
);
//通过容器获取test实例
TestDao tt = (TestDao)beanFac.getBean("test");
tt.sayHello();
}
2.2.2 ApplicationContext
ApplicationContext是BeanFactory的子接口,也称为应用上下文,由org.springframework.context.ApplicationContext接口定义。ApplicationContext接口除了包含BeanFactory的所有功能以外,还添加了对国际化、资源访问、事件传播等内容的支持。
创建ApplicationContext接口实例通常有一下3种方法:
通过ClassPathXmlApplicationContext创建
ClassPathXmlApplicationContext将从类路径目录(src根目录)中寻找指定的XML配置文件。代码如下:
public static void mian(String[] args) { //初始化Spring容器ApplicationContext,加载配置文件 ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml"); //通过容器获取test实例 TestDao tt = new (TestDao)appCon.getBean("test"); tt.sayHello(); }
通过FileSystemXmlApplicationContext创建
FileSystemXmlApplicationContext将从指定文件的绝对路径中寻找XML配置文件,找到并装载完成ApplicationContext的实例化工作。代码如下:
public static void mian(String[] args) { //初始化Spring容器ApplicationContext,加载配置文件 ApplicationContext appCon = new FileSystemXmlApplicationContext("D:\eclipse-workspace\ch1\src\applicationContext.xml"); //通过容器获取test实例 TestDao tt = new (TestDao)appCon.getBean("test"); tt.sayHello(); }
采用绝对路径的加载方式将导致程序的灵活性变差,一般不推荐使用。因此块,通常在Spring的Java应用中采取通过ClassPathXmlApplicationContext类来实例化ApplicationContext容器的方式,而在Web应用中,ApplicationContext容器的实例化工作将交给Web服务器完成。
通过Web服务器实例化ApplicationContext容器
在Web服务器实例化ApplicationContext容器时,一般使用基于org.framework.web.context.ContextLoaderListener的实现方式(需要将spring-web-x.x.x.RELEASE.jar复制到WEB-INF/lib目录中),此方法只需在web.xml中添加如下代码:
<context-param> <!-- 加载src目录下的applicationContext.xml文件 --> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml </param-value> </context-param> <!-- 指定以ContextLoaderListener方式启动Spring容器 --> <listener> <listener-class> org.framework.web.context.ContextLoaderListener </listener-class> </listener>
2.3 依赖注入的类型
在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象(例如属性值)注入Bean组件中。Spring框架的依赖注入通常有两种实现方式,一种是使用构造方法注入,另一种是使用属性的setter方法注入。
2.3.1 使用构造方法注入
Spring框架可以采用Java的反射机制,通过构造方法完成依赖注入。
实例讲解:
创建dao包
创建dao包在service中使用构造方法依赖注入TestDIDao接口对象。
TestDIDao接口代码如下:
package dao; public interface TestDIDao { public void sayHello(); }
TestDIDaoImpl实现类代码如下:
package dao; public class TestDIDaoImpl implements TestDIDao { @Override public void sayHello() { system.out.println("TestDIDao say: Hello, Study hard!"); } }
创建service包
在TestDIServiceImpl中使用构造方法依赖注入TestDIDao接口对象。
TestDIService接口代码如下:
package service; public interface TestDIService { public void sayHello(); }
TestDIServiceImpl实现类代码如下:
package service; import dao.TestDIDao; public class TestDIServiceImlp implements TestDIService { private TestDIDao testDIDao; //构造方法,用于实现依赖注入接口对象testDIDao public TestDIServiceImpl(TestDIDao testDIDao) { super(); this.testDIDao = testDIDao; } @Override public void sayHello() { //调用testDIDao中的sayHello方法 testDIDao.sayHello(); System.out.prinln("TestDIService构造方法注入say: Hello, Study hard!"); } }
编写配置文件
在src根目录下根目录下创建Spring配置文件applicationContext.xml。在配置文件中首先将dao.TestDIDaoImpl类托管给Spring,让Spring创建其对象,然后将service.TestDIServiceImpl类托管给Spring,让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"> <!-- 模拟spring执行过程 创建service实例:BookService bookService = new BookServiceImpl() IoC <bean> 创建dao实例:BookDao bookDao = new BookDaoImpl() IoC 将dao设置给service:bookService.setBookDao(bookDao); DI <property> <property> 用于进行属性注入 name: bean的属性名,通过setter方法获得 setBookDao ##> BookDao ##> bookDao ref :另一个bean的id值的引用 --> <!-- 将指定类TestDIDaoImpl配置给Spring,让Spring创建其实例 --> <bean id="myTestDIDao" class="dao.TestDIDaoImpl" /> <!-- 使用构造方法注入 --> <bean id="testDIService" class="service.TestDIServiceImpl"> <!-- 将myTestDIDao注入到TestDIServiceImpl类的属性testDIDao上 --> <constructor-arg index="0" ref="myTestDIDao" /> </bean> </beans>
创建test包
创建测试类TestDI,代码如下:
package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.TestDIService; public classs TestDI { public static void main(String[] args) { //初始化Spring容器ApplicationContext,加载配置文件 ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml"); //通过容器获取testDIService实例,测试构造方法注入 TestDIService ts = (TestDIService)appCon.getBean("testDIService"); ts.sayHello(); } }
2.3.2 使用属性的setter方法注入
使用setter方法注入是Spring框架中最主流的注入方式,它利用Java Bean规范所定义的setter方法来完成注入,灵活且可读性高。对于setter方法注入,Spring框架也是使用Java的反射机制实现的。
实例讲解:
创建接口实现类TestDIServiceImpl
在service包中创建接口实现类TestDIServiceImpl1,在TestDIServiceImpl1中使用属性的setter方法依赖注入TestDIDao接口对象,代码如下:
package service; import dao.TestDIDao; public class TestDIServiceImpl implements TestDIService { private TestDIDao testDIDao; //添加testDIDao属性的setter方法,用于实现依赖注入 public void set TestDIDao(TestDIDao testDIDao) { this.testDIDao = testDIDao; } @Override public void sayHello() { //调用testDIDao中的sayHello方法 testDIDao.sayHello(); System.out.println("TestDIService setter方法注入 say: Hello, Study hard!"); } }
将TestDIServiceImpl1类托管给Spring
让Spring创建其对象,同时调用TestDISeriveImpl1类的setter方法完成依赖注入。代码如下:
<!-- 使用setter方法注入 --> <bean id="testDIService1" class="service.TestDIServiceImpl1"> <!-- 调用TestDIServiceImpl1类的setter方法,将myTestDIDao注入到TestDIServiceImpl1类的属性testDIDao上 --> <property name="testDIDao" ref="myTestDIDao" /> </bean>
在test中测试setter方法注入
//通过容器获取testDIService实例,测试setter方法注入 TestDIService ts1=(TestDIService)appCon.getBean("testDIService1"); ts1.sayHello();
原文地址:https://www.cnblogs.com/yihangjou/p/11906865.html
- 4大分析工具的代码表白术,520花式秀恩爱!
- yaffsfs.c
- yaffs_bitmap
- 原创 | 实战:R环境下Echart的8种可视化
- Yarn(MapReduce 2.0)下分布式缓存(DistributedCache)的注意事项
- Yaffs_guts(三)
- 浅谈 python multiprocessing(多进程)下如何共享变量
- 文件地址映射之yaffs_GetTnode
- bash/shell 解析命令行参数工具:getopts/getopt
- ssh 双机互信:免密码登录设置步骤及常见问题
- yaffs_guts(一)
- 聊聊 Java 中 HashMap 初始化的另一种方式
- 基于 Hive 的文件格式:RCFile 简介及其应用
- MapReduce 计数器简介
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释