spring揭秘00-ioc定义与ioc容器及集成工厂模式

news2024/11/22 21:49:41

文章目录

  • 【README】
  • 【1】IOC概述
    • 【1.1】ioc定义
    • 【1.2】IOC三种依赖注入方式
  • 【2】ioc服务提供者
    • 【2.1】 ioc服务提供者职责
    • 【2.2】ioc服务提供者如何管理对象间依赖关系
  • 【3】IOC容器
    • 【3.1】BeanFactory
  • 【4】集成工厂模式创建bean
    • 【4.1】静态工厂方法
    • 【4.2】非静态工厂方法
    • 【4.3】FactoryBean接口

【README】

本文总结自《spring揭秘》,作者王福强,非常棒的一本书,墙裂推荐;

本文内容包括ioc概述及ioc容器概述;


【1】IOC概述

【1.1】ioc定义

1.Ioc控制反转,别名是依赖注入DI;

  • (1)反转:就反转在让你从原来的事事必躬亲,转变为现在的享受服务(这是ioc提出的价值所在 );
  • (2)通常情况下: 被注入对象直接依赖于被依赖对象; 但是在IOC场景中,被注入对象与被依赖对象通过IOC服务提供者来打交道,所有的被注入对象和被依赖对象都由IOC服务提供者统一管理; 如ioc容器就是一个ioc服务提供者;
    • 【例】被注入对象与被依赖对象:如Student类声明了 Teacher属性,spring把Teacher对象注入到Student对象,则Student是被注入对象 ,Teacher是被依赖对象;(Teacher是被Student依赖的对象)
    • 其中, 被注入对象与被依赖对象都称为业务对象;

2.IOC作用: IOC是一种帮助我们解耦各业务对象间依赖关系的对象绑定方式;


【1.2】IOC三种依赖注入方式

1)构造方法注入;

  • 优点: 对象构造完成后,马上进入就绪状态,可以马上使用;
  • 缺点: 当依赖对象较多时, 构造器入参列表比较长;

2)Setter方法注入;

  • 优点: 方法可以命名, 允许设置默认值,有良好IDE支持;
  • 缺点:对象构造完成后,无法立即进入就绪状态;

3)实现接口注入;(不推荐,因为有侵入性


【2】ioc服务提供者

ioc服务提供者定义: 管理所有被注入对象和被依赖对象; 如spring ioc容器就是一个ioc服务提供者;

具体的, spring ioc容器有 BeanFactory , ApplicationContext; 其中BeanFactory是基础容器, ApplicationContext继承了 BeanFactory,是高级容器,功能更加丰富

【ApplicationContext】

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    @Nullable
    String getId();

    String getApplicationName();

    String getDisplayName();

    long getStartupDate();

    @Nullable
    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

【2.1】 ioc服务提供者职责

1)业务对象的构建管理(创建bean): 即业务对象无需关心所依赖的对象如何构建(bean如何创建),由IOC服务提供者来完成;

2)业务对象间的依赖绑定(绑定对象间依赖关系):IOC服务服务提供者通过结合之前构建和管理的所有业务对象,以及各个业务对象间可以识别的依赖关系,将这些对象所依赖的对象注入绑定;

【2.2】ioc服务提供者如何管理对象间依赖关系

1)直接编码方式; (不推荐
2)配置文件方式: 比较常见的依赖管理方式; 如使用普通文本文件,XML,properties文件,等都可以作为管理依赖关系的载体;
3)元数据方式:即通过注解实现; 直接在类中使用元数据信息(注解)来标注对象间的依赖关系;


【3】IOC容器

1)ioc 容器概述:

  • ioc容器是一个ioc服务提供者;
  • Spring的Ioc容器是一个提供ioc支持的轻量级容器;
  • spring提供了两种容器: BeanFactory ,ApplicationContext ; 其中 ApplicationContext 继承自 BeanFactory ;

2)Spring还在ioc容器基础上提供了AOP框架支持,企业级服务集成等服务,如下图所示。

在这里插入图片描述

【3.1】BeanFactory

**1)容器1-BeanFactory:**基础类型IOC容器(懒汉式初始化 ), 提供完整的IOC服务支持; 如果没有特殊指定,默认采用延迟初始化策略;

  • 适用场景: 适用于资源有限,功能要求不是很严格的场景;
  • 作为spring基本的IOC容器, BeanFactory职责包括业务对象注册和对象间依赖关系绑定;

2)容器2-ApplicationContext(饿汉式初始化: 在BeanFactory基础上构建,是比较高级的容器;ApplicationContext管理的对象,在ApplicationContext容器启动后,默认全部初始化并绑定完成;

补充: ApplicationContext 继承自 BeanFactory ;


【4】集成工厂模式创建bean

1)背景:在系统开发中 ,需要集成第三方库或实例化bean过程复杂(如创建bean的代理,添加上下文),需要通过工厂模式创建bean,以简化代码及解耦被注入对象与被依赖对象接口实现类, 如 使用第三方库 SimpleClientHttpRequestFactory 创建http连接对象, 就是通过工厂方法模式实例化bean ;

2)对于下图中的Foo与BarInterface及BarInterfaceImpl, 可以通过工厂模式解除 Foo 与 BarInterfaceImpl具体实现类 间的耦合关系; (依赖抽象而不应该依赖具体实现 BarInterfaceImpl , 否则实现类有改动,则被注入对象Foo也会改动,不灵活,且回归测试成本高
在这里插入图片描述

3)spring ioc容器提供了对3种工厂模式的集成支持,包括静态工厂方法,非静态工厂方法, FactoryBean接口 ;

  • 静态工厂(静态工厂方法模式): 简单,但从头到尾都有且只有一个工厂;即工厂不抽象(1个),产品可以抽象(多个);
  • 非静态工厂(工厂方法模式): 相对灵活,调用方依赖的产品和工厂都可以抽象;
  • FactoryBean: 是一个接口,Spring容器提供的一种可以扩展容器对象实例化的接口; 即业务工厂实现FactoryBean接口, 重写 getObject() 方法,扩展bean创建逻辑 ;

补充1: 静态工厂与非静态工厂, 其产品和工厂可以抽象也可以不抽象;

补充2:特例, 非静态工厂的特例是抽象工厂,其工厂必须抽象;

【4.1】静态工厂方法

【CarStaticFactoryMain】静态工厂入口main函数

public class CarStaticFactoryMain {
    public static void main(String[] args) {
        ApplicationContext container = new ClassPathXmlApplicationContext("beans0403factorymethod.xml");
        ICar electricCar = container.getBean("electricCar", ICar.class);
        ICar electricCar2 = container.getBean("electricCar", ICar.class);
        ICar electricCar3 = container.getBean("electricCar", ICar.class);
        electricCar.drive();
        electricCar2.drive();
        electricCar3.drive();
    }
}

【beans0403factorymethod.xml】

 <!-- 静态工厂实例化bean  -->
    <bean id="electricCar" class="com.tom.springnote.chapter04.t0403xmlfactorymethod.CarStaticFactory"
          factory-method="getInstance" scope="prototype"/>

【CarStaticFactory】汽车静态工厂

public class CarStaticFactory {
    private static final AtomicInteger INCREMENTOR = new AtomicInteger(0);

    public static ICar getInstance() {
        return new ElectricCar("特斯拉汽车" + INCREMENTOR.getAndIncrement());
    }
}

【ICar】 抽象产品 (接口或抽象类都可以)

public abstract class ICar {
    private String name = "";

    public ICar() {
    }

    public ICar(String name) {
        this.name = name;
    }

    abstract void drive();

    public String getName() {
        return name;
    }
}

【ElectricCar】电动车,具体产品

public class ElectricCar extends ICar {
    public ElectricCar(String name) {
        super(name);
    }
    @Override
    public void drive() {
        System.out.println("name=" + getName() + ", 电池驱动, 自动驾驶");
    }
}

【打印日志】

name=特斯拉汽车0, 电池驱动, 自动驾驶
name=特斯拉汽车1, 电池驱动, 自动驾驶
name=特斯拉汽车2, 电池驱动, 自动驾驶

补充: 本文的静态工厂代码,对产品做了抽象,依赖ICar,而不是 ElectricCar 这个具体car;

在实际开发过程中, 静态工厂可以抽象也可以不抽象产品;

  • 工厂与产品是同一个类,这又是静态工厂的特例,叫简单工厂, 如 Integer.valueOf ;
  • 工厂不抽象,但产品抽象;如 List.of(…)

【Integer.valueOf】

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

【List.of()】

static <E> List<E> of(E e1, E e2) {
        return new ImmutableCollections.List12<>(e1, e2);
    }

【4.2】非静态工厂方法

非静态工厂方法对工厂和产品都做了抽象;

【CarNonStaticFactoryMain】非静态工厂方法入口main

public class CarNonStaticFactoryMain {
    public static void main(String[] args) {
        ApplicationContext container = new ClassPathXmlApplicationContext("beans0403factorymethod.xml");
        ICar car = container.getBean("petrolCar", ICar.class);
        ICar car2 = container.getBean("petrolCar", ICar.class);
        ICar car3 = container.getBean("petrolCar", ICar.class);
        car.drive();
        car2.drive();
        car3.drive();
    }
}

【beans0403factorymethod.xml】

<!-- 02 非静态工厂实例化bean  -->
<bean id="carNonStaticFactory" class="com.tom.springnote.chapter04.t0403xmlfactorymethod.CarNonStaticFactoryImpl" />
<bean id="petrolCar" factory-bean="carNonStaticFactory" factory-method="getInstance" scope="prototype" />

【CarNonStaticFactoryImpl】非静态工厂,具体工厂

public class CarNonStaticFactoryImpl implements ICarFactory {

    private static final AtomicInteger INCREMENTOR = new AtomicInteger(0);

    @Override
    public ICar getInstance() {
        return new PetrolCar("奔驰汽车" + INCREMENTOR.getAndIncrement());
    }
}

【PetrolCar】继承ICar抽象类,具体产品

public class PetrolCar extends ICar {

    public PetrolCar(String name) {
        super(name);
    }

    @Override
    public void drive() {
        System.out.println("name=" + getName() + ", 汽油驱动,人工驾驶");
    }
}

【打印日志】

name=奔驰汽车0, 汽油驱动,人工驾驶
name=奔驰汽车1, 汽油驱动,人工驾驶
name=奔驰汽车2, 汽油驱动,人工驾驶

【4.3】FactoryBean接口

factoryBean是一个接口, Spring容器提供的一种可以扩展容器对象实例化逻辑的接口; 定义如下:

【FactoryBean接口】

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

spring容器内部很多地方使用到了FactoryBean接口实例化bean

  • JndiObjectFactoryBean
  • LocalSessionFactoryBean
  • SqlMapClientFactoryBean
  • ProxyFactoryBean

使用FactoryBean创建bean代码示例:

【CarFactoryBeanImplMain】FactoryBean入口main

public class CarFactoryBeanImplMain {
    public static void main(String[] args) {
        ApplicationContext container = new ClassPathXmlApplicationContext("beans0403factorymethod.xml");
        ICar car = container.getBean("electricCarFactoryBean", ICar.class);
        ICar car2 = container.getBean("electricCarFactoryBean", ICar.class);
        ICar car3 = container.getBean("electricCarFactoryBean", ICar.class);
        car.drive();
        car2.drive();
        car3.drive();
    }
}

【beans0403factorymethod.xml】

<!-- 03 实现factorybean接口实例化bean  -->
    <bean id="electricCarFactoryBean" class="com.tom.springnote.chapter04.t0403xmlfactorymethod.CarFactoryBeanImpl"
          scope="prototype" />

【CarFactoryBeanImpl】 FactoryBean接口实现类

public class CarFactoryBeanImpl implements FactoryBean<ICar> {

    private static final AtomicInteger start = new AtomicInteger(0);

    @Override
    public ICar getObject() throws Exception {
        return new ElectricCar("FactoryBean特斯拉" + start.getAndIncrement());
    }

    @Override
    public Class<?> getObjectType() {
        return ICar.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

【打印日志】

name=FactoryBean特斯拉0, 电池驱动, 自动驾驶
name=FactoryBean特斯拉1, 电池驱动, 自动驾驶
name=FactoryBean特斯拉2, 电池驱动, 自动驾驶

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046342.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT+CUDA 同时编译Qt和CUDA代码

工作需要把cuda的代码移植到QT中&#xff0c;和Qt项目一起编译&#xff0c;这里记录一下。 前期准备 1.安装CUDA 电脑需要安装好 CUDA&#xff0c;可以看我的这篇文章安装&#xff1a;Windows和WSL安装CUDA-CSDN博客 使用命令 nvcc --version 查看安装的 CUDA 版本。 CUDA 的默…

通过API构建开放式外卖系统平台:合作伙伴的集成与管理

随着外卖行业的迅速发展&#xff0c;外卖系统平台的开放性和可扩展性变得尤为重要。通过API构建一个开放式的外卖系统平台&#xff0c;企业可以更轻松地与合作伙伴进行集成和管理。本文将探讨如何通过API构建开放式外卖系统平台&#xff0c;并通过代码示例展示与合作伙伴的集成…

md-editor-v3适配VUE3的MarkDown编辑器-好用-简单-免费

官方文档&#xff1a; https://imzbf.github.io/md-editor-v3/zh-CN/indexhttps://imzbf.github.io/md-editor-v3/zh-CN/index 效果演示&#xff1a;&#xff08;支持黑暗模式切换&#xff09; toolbar包括&#xff1a; [bold,underline,italic,strikeThrough,title,sub,sup…

系统编程 day13 进程5

前提&#xff1a; 信息量&#xff1a;线程间有序的进行工作 资源的个数 机制&#xff1a;描述可使用资源的个数 操作&#xff1a; p操作&#xff1a;使用这个资源&#xff0c;表示资源个数减1 v操作&#xff1a;产生这个资源&#xff0c;表示资源个数加1 p操作逻辑&…

CoCoOp(论文解读):Conditional Prompt Learning for Vision-Language Models

摘要 随着预训练的视觉语言模型&#xff08;如 CLIP&#xff09;的兴起&#xff0c;研究使这些模型适应下游数据集的方法变得至关重要。最近CoOp方法将NLP领域中的提示学习引入到视觉领域中&#xff0c;来调整预训练的视觉语言模型。具体来说&#xff0c;CoOp 将提示中的上下文…

DataGridView用法合集(9):添加控件

目录 45. DataGridView列中显示选择框CheckBox 46. DataGridView中显示下拉框ComboBox 47. DataGridView单击打开下拉框 48. DataGridView中显示按钮 49. DataGridView中显示链接 50. DataGridView中显示图像 45. DataGridView列中显示选择框CheckBox [VB.NET] 添加Chec…

MySQL5.7数据库---入门教程(小白教程)

一、MySQL安装 本文以MySQL5.7安装为例。在设置完root密码和添加一个用户后&#xff0c;一路默认。 1、 2、通过点击红圈里的箭头选择对应的版本。 3、 4、端口&#xff08;Port&#xff09;一般默认不需要更改。 5、 二、配置环境变量 配置环境变量可以方便在win系统中cmd…

HarmonyOS 端云一体化 -- 项目初始化

HarmonyOS 端云一体化 – 项目初始化 端云一体化官方简介 本文档基于 api9 编写本来我想用最新版的api搞&#xff0c;但是在 AppFallery Connect 上创建项目的时候有bug&#xff0c;没没办法成功创建应用&#xff0c;无奈只能切换到 api9 版本。 1.新建项目 1.1 登录华为官…

突破大模型极限!GLM-4-long百万长文本模型上线bigmodel.cn

最近业务上多了长文本的需求&#xff0c;因为要在prompt里面塞进比较多的rag内容&#xff0c;以供决策&#xff0c;且这些召回的内容&#xff0c;都有可能用到。这非常考验大模型的长文本能力&#xff0c;技术选型上都要着重考察这部分。 正巧&#xff0c;上次清影试用后&…

游戏开放式新手引导框架设计

强制性引导&#xff1a;只能点某个按钮 优&#xff1a;程序简单 缺&#xff1a; 玩家体验差 开放式引导&#xff1a;不强制点 优&#xff1a;玩家体验好 缺&#xff1a; 程序复杂 需求分析&#xff1a; 1.开放式引导&#xff0c;引导是到达某个条件后进行一系列行为&#xff08…

水星Mercury X1轮式人形机器人结合openc算法&STag标记码视觉系统实现精确抓取!

本案例展示了如何利用视觉系统提升机械臂的抓取精度&#xff0c;成功实现了人形机器人的双臂抓取不在局限于单臂抓取。 引言 如今市面上已经有了许多不同类型的人形机器人&#xff0c;涵盖了服务行业和医疗行业等各个领域。这些机器人以其智能化和自动化的特性逐渐融入我们的日…

比例PQ阀信号放大器的选择

比例PQ阀信号放大器的选择时&#xff0c;需要考虑一系列的因素以确保放大器能精确匹配比例阀的需求&#xff0c;保障液压系统的高效和稳定运行。根据所控制的比例阀类型&#xff0c;选择与之兼容的放大器型号。如各厂商不带反馈比例方向阀、比例溢流阀、比例减压阀等均可用BEUE…

RabbitMQ 集群部署方案

RabbitMQ 一、安装 RabbitMQ二、更改配置文件三、配置集群四、测试 环境准备&#xff1a;三台服务器&#xff0c;系统是 CentOS7IP地址分别是&#xff1a; rabbitmq1&#xff1a;192.168.152.71rabbitmq2&#xff1a;192.168.152.72rabbitmq3&#xff1a;192.168.152.73 一、…

【一键操作】【包运行及安装教程】2024数学建模国赛(高教社杯)Latex论文模板

数学建模国赛创办于1992年&#xff0c;每年一届&#xff0c;是首批列入“高校学科竞赛排行榜”的19项竞赛之一。 作为一个重量级的赛事&#xff0c;一次参赛将众生受益&#xff0c;所以相信很多同学都在为了国奖而努力&#xff0c;所以针对大家的参赛论文&#xff0c;我们之前分…

LVS集群的NAT模式和DR模式

LVS简介 LVS&#xff08;Linux Virtual Server&#xff09;是一个用于负载均衡的开源软件项目&#xff0c;旨在通过集群技术实现高性能、高可用的服务器系统。它运行在Linux操作系统上&#xff0c;并且可以利用内核级的资源来提高性能和稳定性。 LVS 体系结构 LVS架构 主要…

Redis远程字典服务器(7)—— set类型详解

目录 一&#xff0c;基本情况 二&#xff0c;常用命令 2.1 sadd 2.2 smembers&#xff0c;sismember 2.3 spop&#xff0c;srandmember 2.3 smove&#xff0c;srem 2.4 sinter&#xff0c;sinterstore求交集 2.5 sunion&#xff0c;sunionstore求并集 2.6 sdiff&#…

Mysql视图整理

理论 初级语法及操作 操作基于navicat视图化&#xff0c;其他管理工具基本类似 参考即可 这里附上官网免费版下载链接&#xff1a;Navicat Premium Lite | 简单的数据库管理和开发工具 首先&#xff1a;选择选中数据库--》最上面的视图--》新建视图--》 我们可以看到这里&a…

three.js 几何体、材质和网格模型

场景Scene、相机Camera、渲染器Renderer初始化完成之后&#xff0c;可以向场景中添加一个简单的模型进行展示。在此之前需要了解三个概念&#xff1a;几何体、材质、网格模型。 几何体&#xff1a;表示物体的几何形状。材质&#xff1a;表示物体的外观效果。网格模型&#xff…

springboot的学习(一):springboot的基础

简介 springboot的基础的知识点的学习总结 springboot 设计目的是为了简化spring应用的初始搭建和开发过程。 简单例子 new project&#xff0c;一般用这个阿里的地址&#xff1a;https://start.aliyun.com/ 点击next&#xff0c;选择jdk版本 点击next&#xff0c;选择模…

88.SAPUI5 Model Binding的问题-在view更改数据,model却不变

目录 1.背景 2.sap.ui.model.BindingMode sap.ui.model.BindingMode.OneWay sap.ui.model.BindingMode.TwoWay 3.oModel.setDefaultBindingMode 方法说明 execOneWay方法 execTwoWay方法 1.背景 在做一个UI5项目&#xff0c;后台读取sap.ui.model.Model后&#xff0c;把…