当前位置: 首页 > news >正文

(十三)Spring教程——依赖注入之工厂方法注入

1.工厂方法注入

        工厂方法是在应用中被经常使用的设计模式,它也是控制反转和单例设计思想的主要实现方法。由于Spring IoC容器以框架的方式提供工厂方法的功能,并以透明的方式开放给开发者,所以很少需要手工编写基于工厂方法的类。正是因为工厂方法已经成为底层设施的一部分,因此工厂方法对于实际编码的重要性就降低了。不过在一些遗留系统或第三方类库中,我们还是会遇到工厂方法,这时可以使用Spring工厂方法注入的方式进行配置。

1.1非静态工厂方法

        有些工厂方法是非静态的,即必须实例化工厂类后才能调用工厂方法。下面为Car提供一个非静态的工厂类,创建一个CarFactory.java类,该类的代码如下:

package com.example.servlet001.bean;public class CarFactory {/*** 创建Car的工厂方法* @return*/public Car createHongQiCar(){Car car=new Car();car.setBrand("红旗CA2000");return car;}}

        工厂类负责创建一个或多个目标类实例,工厂类方法一般以接口或抽象类变量的形式返回目标类实例。工厂类对外屏蔽了目标类的实例化步骤,调用者甚至无须知道具体的目标类是什么。上述的CarFactory工厂类仅负责创建Car类型的对象,下面的配置片段使用CarFactory为Car提供工厂方法的注入,代码如下所示:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"><!--工厂类Bean--><bean id="carFactory" class="com.example.servlet001.bean.CarFactory"></bean><bean id="car" factory-bean="carFactory" factory-method="createHongQiCar"></bean></beans>

        由于CarFactory工厂类的工厂方法不是静态的,所以首先需要定义一个工厂类的Bean,然后通过factory-bean引用工厂类实例,最后通过factory-method指定对应的工厂类方法。

修改测试类代码对配置进行测试,测试类的代码如下所示:
 

package com.example.servlet001;import com.example.servlet001.bean.Car;import org.springframework.beans.factory.support.DefaultListableBeanFactory;import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;import org.springframework.core.io.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternResolver;public class Demo1 {public static void main(String[] args) {//通过xml配置文件的方式装在BeanResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();Resource res = resolver.getResource("test.xml");DefaultListableBeanFactory factory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);reader.loadBeanDefinitions(res);Car car=factory.getBean("car", Car.class);System.out.println("brand:"+car.getBrand());System.out.println("price:"+car.getPrice());System.out.println("maxSpeed:"+car.getMaxSpeed());}}

        运行该程序后的结果显示如下:

1.2静态工厂方法

         很多工厂类方法都是静态的,这意味着用户无须创建工厂类实例的情况下就可以调用工厂类方法,因此,静态工厂方法比非静态工厂方法更易使用。下面对CarFactory进行改造,将其createHongQiCar()方法调整为静态的,代码清单如下:

package com.example.servlet001.bean;public class CarFactory {/*** 创建Car的工厂方法* @return*/public static Car createHongQiCar(){Car car=new Car();car.setBrand("红旗CA2000");return car;}}

        当使用静态工厂类型的方法后,用户就无须在配置文件中定义工厂类的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"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="car" class="com.example.servlet001.bean.CarFactory" factory-method="createHongQiCar"></bean></beans>

        直接在<bean>中通过class属性指定工厂类,然后通过factory-method指定对应的工厂方法。

然后重新运行该程序后的结果如下图所示

        可以看到运行后得到的结构是跟上述非静态工厂方法是一样的,只是实现的方式不同。

2.选择注入方式的考量

        Spring提供了3中可供选择的注入方式,在实际应用中,选择哪种注入方式并没有统一的标准。下面是支持使用构造函数注入的理由:

①构造函数可以保证一些重要的属性在Bean实例化时就设置好,避免因为一些重要属性没有提供而导致一个无用的Bean实例的情况。

②不需要为每个属性提供Setter方法,减少了类的方法个数。

③可以更好地封装类变量,不需要为每个属性指定Setter方法,避免外部错误的调用。

        更多的开发者可能倾向于使用属性注入的方式,他们反对构造函数注入的理由如下:

①如果一个类的属性众多,那么构造函数的签名将变成一个庞然大物,可读性很差。

②灵活性不强,在有些属性是可选的情况下,如果是通过构造函数注入,也需要为可选的参数提供一个null值。

③如果有多个构造函数,则需要考虑配置文件和具体构造函数匹配歧义的问题,匹配上相对复杂。

④构造函数不利于类的继承和拓展,因为子类需要引用父类复杂的构造函数。

⑤构造函数注入有时会造成循环依赖的问题。

        其实构造函数注入和属性注入各有自己的应用场景,Spring并没有强制用户使用哪一种方式,用户完全可以根据个人偏好做出选择,在某些情况下使用构造函数注入,而在另一些情况下使用属性注入。对于一个全新开发的应用来说,我们不推荐使用工厂方法的注入方式,因为工厂方法需要额外的类和代码,这些功能和业务是没有关系的,既然Spring容器已经以一种更优雅的方式实现了传统工厂模式的所有功能,那么我们大可不必再去做这项重复性的工作。

相关文章:

(十三)Spring教程——依赖注入之工厂方法注入

1.工厂方法注入 工厂方法是在应用中被经常使用的设计模式&#xff0c;它也是控制反转和单例设计思想的主要实现方法。由于Spring IoC容器以框架的方式提供工厂方法的功能&#xff0c;并以透明的方式开放给开发者&#xff0c;所以很少需要手工编写基于工厂方法的类。正是因为工厂…...

Redission中的Lua脚本写法、理解

对于Redission看门狗机制中的为了保证原子性的Lua脚本的写法规则是什么样的呢 &#xff1f; 对于源码中的Lua脚本又是什么意思&#xff1f; 我们一起来看一下 首先&#xff0c;我们先基本的熟悉一下lua脚本的逻辑 在Lua脚本中&#xff0c;if (…) then … end 语句的执行过程…...

视频共享融合赋能平台LntonCVS视频监控管理平台视频云解决方案

LntonCVS是基于国家标准GB28181协议开发的视频监控与云服务平台&#xff0c;支持多设备同时接入。该平台能够处理和分发多种视频流格式&#xff0c;包括RTSP、RTMP、FLV、HLS和WebRTC。主要功能包括视频直播监控、云端录像与存储、检索回放、智能告警、语音对讲和平台级联&…...

GraphRAG + GPT-4o mini 低成本构建 AI 图谱知识库

更好的效果&#xff0c;更低的价格&#xff0c;听起来是不是像梦呓&#xff1f; 限制 首先&#xff0c;让我们来介绍一个词&#xff1a;RAG。 简单来说&#xff0c;RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09; 的工作原理是将大型文档…...

全国区块链职业技能大赛第十套区块链产品需求分析与方案设计

任务1-1:区块链产品需求分析与方案设计 养老保险平台中涉及到参保人、社保局、公安局、工作单位等参与方,他们需要在区块链养老保险平台中完成账户注册、身份上链、社保代缴、信息核查等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于养老保险…...

分布式Apollo配置中心搭建实战

文章目录 环境要求第一步、软件下载第二步、创建数据库参考文档 最近新项目启动&#xff0c;采用Apollo作为分布式的配置中心&#xff0c;在本地搭建huanj 实现原理图如下所示。 环境要求 Java版本要求&#xff1a;JDK1.8 MySql版本要求&#xff1a;5.6.5 Apollo版本要求&…...

Android monkey命令和monkey脚本详解

Monkey命令 monkey 是 Android 平台上一个非常有用的工具&#xff0c;它可以帮助开发者在设备上生成随机的用户事件流&#xff0c;如按键输入、触摸屏手势等&#xff0c;以此来测试应用的稳定性。这对于发现应用中的崩溃、异常和性能问题特别有用。 基本语法 adb shell monk…...

vue 实现对图片的某个区域点选, 并在该区域上方显示该部分内容

目录 1、通义灵码实现&#xff1a; 2、csdn的C知道&#xff1a; 3、百度comate&#xff1a; 1、通义灵码实现&#xff1a; 在 Vue 中实现对图片某个区域的点选并显示该区域属于哪一部分&#xff0c;通常涉及到几个关键步骤&#xff1a; 图片区域划分&#xff1a; 首先&#…...

配置文件格式 INI 快速上手

文章目录 1.简介2.语法节键值对注释大小写空白行数据类型字符串 (String)整数 (Integer)浮点数 (Float)布尔值 (Boolean)列表 (List) 3.示例4.解析参考文献 1.简介 INI 的全称是 Initialization&#xff0c;即为初始化文件&#xff0c;最早是 Windows 系统配置文件所采用的格式…...

基于WebGoat平台的SQL注入攻击

目录 引言 一、安装好JAVA 二、下载并运行WebGoat 三、注册并登录WebGoat 四、模拟攻击 1. 第九题 2. 第十题 3. 第十一题 4. 第十二题 5. 第十三题 五、思考体会 1. 举例说明SQL 注入攻击发生的原因。 2. 从信息的CIA 三要素&#xff08;机密性、完整性、可用性&…...

SpringMvc有几个上下文

你好&#xff0c;我是柳岸花明。 SpringMVC作为Spring框架的重要组成部分&#xff0c;其启动流程和父子容器机制是理解整个框架运行机制的关键。本文将通过一系列详细的流程图&#xff0c;深入剖析SpringMVC的启动原理与父子容器的源码结构。 SpringMVC 父子容器 父容器的创建 …...

k8s部署rabbitmq集群

1 部署集群 1.1 安装 # 创建一个中间件的命名空间 kubectl create namespace middleware # 创建ConfigMap,包含RabbitMQ的配置文件内容 kubectl apply -f rabbitmq-configmap.yaml # 配置用于存储RabbitMQ数据的PersistentVolume&#xff08;PV&#xff09;和PersistentVolum…...

Python利用包pypinyin汉字转拼音(处理多音字)

一、汉字转拼音 在python中将汉字的拼音输出可以采用pypinyin包&#xff0c;一下是简单的demo示例&#xff1a; 默认调用pinyin方法转换时时默认时带声调的&#xff0c;不带声调需要添加“styleStyle.NORMAL”参数。 from pypinyin import pinyin, Styledef pinyin_transfer…...

推荐系统三十六式学习笔记:工程篇.常见架构24|典型的信息流架构是什么样的

目录 整体框架数据模型1.内容即Activity2.关系即连接 动态发布信息流排序数据管道总结 从今天起&#xff0c;我们不再单独介绍推荐算法的原理&#xff0c;而是开始进入一个新的模块-工程篇。 在工程实践的部分中&#xff0c;我首先介绍的内容是当今最热门的信息流架构。 信息…...

解决QEMU无法从非0x80000000处开始执行

解决QEMU无法从非0x80000000处开始执行 1 背景介绍2 问题描述3 原因分析4 解决办法5 踩坑回忆5.1 坑1 - 怀疑设备树有问题5.2 坑2 - 怀疑QEMU中内存未写入成功5.3 QEMU地址空间分析过程 1 背景介绍 在使用NEMU与QEMU做DiffTest的场景下&#xff0c;运行的固件为《RISC-V体系结…...

AI在候选人评估中的作用:精准筛选与HR决策的助力

一、引言 随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已逐渐渗透到各个行业和领域&#xff0c;人力资源管理&#xff08;HRM&#xff09;亦不例外。在候选人评估的环节中&#xff0c;AI技术以其高效、精准的特性&#xff0c;正在逐步改变着传统的招…...

自动化测试的艺术:Xcode中GUI测试的全面指南

自动化测试的艺术&#xff1a;Xcode中GUI测试的全面指南 在软件开发过程中&#xff0c;图形用户界面&#xff08;GUI&#xff09;测试是确保应用质量和用户体验的关键环节。Xcode&#xff0c;作为苹果的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了一套强大…...

uniapp封装请求拦截器,封装请求拦截和响应拦截的方法

首先我们先看一下uni官方给开发者提供的uni.request用来网络请求的api 1 2 3 4 5 6 7 8 9 uni.request({ url: , method: GET, data: {}, header: {}, success: res > {}, fail: () > {}, complete: () > {} }); 可以看到我们每次请求数据的时候都需…...

开局一个启动器:从零开始入坑ComfyUI

前几天刷某乎的时候看到了一位大佬写的好文&#xff0c;可图 IP-Adapter 模型已开源&#xff0c;更多玩法&#xff0c;更强生态&#xff01; - 知乎 (zhihu.com) 久闻ComfyUI大名&#xff0c;决定试一下。这次打算不走寻常路&#xff0c;不下载现成的一键包了&#xff0c;而是…...

34_YOLOv5网络详解

1.1 简介 YOLOV5是YOLO&#xff08;You Only Look Once&#xff09;系列目标检测模型的一个重要版本&#xff0c;由 Ultralytics 公司的Glenn Jocher开发并维护。YOLO系列以其快速、准确的目标检测能力而闻名&#xff0c;尤其适合实时应用。YOLOV5在保持高效的同时&#xff0c…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...