spring-Ioc学习笔记

spring 是面向Bean的编程

  • Ioc (Inversion of Control) 控制反转/依赖注入(DI:Dependency Injection)
  • Aop(Aspect Oriented Programming) 面向切面编程

spring框架概述

spring overview

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

spring 在启动时会把所有的作用域为单例的bean都进行实例化

这时我们看到testDao在spring初始化之前就实例化,而testBiz是spring初始化后实例化的。当我们把配置文件中的作用域修改成单例模式后

运行程序查看结果

testBiz在spring初始化之前完成了实例化



来自为知笔记(Wiz)


posted on 2020-10-04 23:30  白衣风云  阅读(179)  评论(0编辑  收藏  举报

导航