spring-Ioc学习笔记
spring 是面向Bean的编程
- Ioc (Inversion of Control) 控制反转/依赖注入(DI:Dependency Injection)
- Aop(Aspect Oriented Programming) 面向切面编程
spring框架概述
Bean的作用域
默认情况下为单例模式:scope="singleton"
<bean id ="user" class="entity.User"/>
<bean is = "user" class= "entity.User" scope="singleton"/>
类别 | 说明 |
---|---|
singleton(单例) | 在spring容器中仅存在一个共享的Bean实例 |
prototype(原型) | 每次从容器中都是获取一个新的实例 |
request | 每次请求都会创建一个新的Bean实例 |
session | 同一个HTTP请求共享一个Bean实例 |
global Session | 同一个全局Session共享一个Bean实例 |
注:request,session, global session模式,仅适用于WebApplicationContext环境
spring Bean封装机制
- Spring 以Bean的方式管理所有的组件,java EE 的全部组件都是被视为Bean管理
- Bean 在Spring 的容器中运行,Spring负责创建Bean的实例,并管理其生命同期
BeanFactory
- 由org.springframework.beans.factory.BeanFactory接口定义
- BeanFactory 是工厂模式(Factory pattern)的实现,负责创建和管理bean
ApplicationContext 是BeanFactory的子接口
- 实现类 ClassPathXmlApplicationContext(用于查找根目录下的配置文件)
- 实现类 FileSystemXmlApplicationContext(用于查找系统盘下的配置文件)
- 当我们有多个配置文件时
ApplicationContext context = new ClassPathXmlApplication(new String[]{
"conf/bean1.xml", "conf/bean2.xml"
})
控制反转/依赖注入
- 将组件对象的控制权从代码本身转移到外部容器
- 组件化的思想:分离关注点,接口与实现分离
- 依赖的注入:将组件的构建和使用分开
Ioc使用两大关键技术一个设计模式
- JDOM: 用于解析配置文件
- 反射机制
- 工厂模式(单例模式)
spring Ioc原理解析
- 导入所需要的所需要的jar包
- 创建接口ITestDao
- 分别创建两个实现类TestDao 和NewDao
- 创建业务类TestBiz,当我们需要调用ITestDao时,必须new一个实例
耦合 - 当直接new 一个实例时,代码就高度耦合,那么怎么解耦合呢,这里引入工厂模式,我们创建一个工厂类,把new 实例的权利交给工厂,我们直接和工厂要就行
- 业务层通过工厂得到一个ITestDao的实例
- 这样数据层和业务层就实现了解耦合
那么spring是怎么实现解耦合的呢,接下来我们接着修改
- 修改业务层,使之面向接口的实现
- 创建接口ITestBiz
- 修改TestBiz类
- 实现ITestBiz接口
- 声明dao层接口的属性,并提供getter/setter方法
- 编写spring的配置文件,applicationContext.xml
- 导入schema文件
- 在spring配置文件里声明需要spring管理的Bean,就是创建一个对象
- 创建测试类TestIoc
- 如果我们现在通过new TestBiz类,会得到什么?
- 运行main方法
- 报错空指针异常
- 那么,应该怎么做呢?当我们把bean交给spring容器管理后,我们应该向spring索要需要的bean
- 首先,把配置文件applicationContext.xml读取进来
- 通过 getBean()方法得到所需要的实例,传入配置文件声明的bean的id
- 运行main方法
- 实现过程,通过getBean()传入的参数testBiz找到 -----> 配置文件中的id为testBiz的bean组件-----》实例化对象(new TestBiz())---->在TestBiz类中有一个dao的属性------>调用setData()方法给dao属性初始化(testBiz.setDao(testDao))----->通过引用的testDao找到id为testDao的bean ---->实例化一个TestDao对象(new TestDao())
- 当我们需求变更时,我们直接在配置文件中替换组件就行,例如我们想要NewDao的实例
- 直接运行main方法,看看输出了什么?
- 输出了NewDao中的数据
总结:spring 扮演了一个工厂的角色,所有的类都是一个组件,一个bean
默认情况下spring 只会创建一个对象,所有的调用者共享一个实例,我们来验证一下
- 我们来再一次调用getBean()方法,赋值给新的变量,我们来判断两个变量的内存地址是否相等
- 结果为true ,我们在配置文件中把bean 的作用域修改为prototype
- 接着我们来再次运行
- 结果为false