(十三)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容器已经以一种更优雅的方式实现了传统工厂模式的所有功能,那么我们大可不必再去做这项重复性的工作。

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

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

相关文章

如何从网站获取表格数据

1.手动复制粘贴 最简单的方法是直接在网页上手动选择表格内容&#xff0c;然后复制粘贴到Excel或其他表格处理软件中。这种方法适用于表格较小且不经常更新的情况。 2.使用浏览器插件 有许多浏览器插件可以帮助从网页中提取表格数据&#xff0c;例如&#xff1a; -TableCapt…

SSRF过滤攻击

SSRF绕过&#xff1a; 靶场地址&#xff1a;重庆橙子科技SSRF靶场 这个是毫无过滤的直接读取&#xff0c;但是一般网站会设置有对SSRF的过滤&#xff0c;比如将IP地址过滤。 下面是常用的绕过方式&#xff1a; 1.环回地址绕过 http://127.0.0.1/flag.php http://017700…

相机怎么选(不推荐,只分析)

title: 相机怎么选 tags: [相机, 单反相机] categories: [其他, 相机] 最近准备购买&#xff0c;相机怎么选&#xff0c;我去搜索了许多文章&#xff0c;整理了一篇小白挑选技术篇&#xff0c;供大家参考。 分类 胶片相机 需要装入胶卷才能使用的相机&#xff0c;拍照后可直…

永磁同步电机无速度算法--非线性磁链观测器

非线性磁链观测器顾名思义观测器的状态变量为磁链值&#xff0c;观测的磁链值收敛于电机实际磁链值&#xff0c;观测器收敛。非线性是由于观测器存在sin和cos项&#xff0c;所以是非线性观测器 一、原理介绍 表贴式永磁同步电机αβ轴电压方程: 将公式变换 定义状态变量X: 定…

Milvus 向量数据库进阶系列丨部署形态选型

本系列文章介绍 在和社区小伙伴们交流的过程中&#xff0c;我们发现大家最关心的问题从来不是某个具体的功能如何使用&#xff0c;而是面对一个具体的实战场景时&#xff0c;如何选择合适的向量数据库解决方案或最优的功能组合。在 “Milvus 向量数据库进阶” 这个系列文章中&…

Java实现打印功能

JPG图片文件格式打印实现 打印JPG图片格式的文件&#xff0c;本次采用的Java原生的打印方式。 public static void main(String[] argv) throws Exception {File file new File("E:\\a.jpg");String printerName "HP MFP M436 PCL6";//打印机名包含字串…

vite+vue3项目,开发时候正常,打包后router-view不渲染

这是个很奇怪的问题&#xff0c;但是基本上命名或者引入文件的方式导致的。要么文件名与系统的某些标签名一样&#xff0c;要么就是routes写成了routers。还有一种就是导入方式错误的 错误截图&#xff1a; 正确引入截图&#xff1a;

Flink大状态作业调优——DataStream篇

一、Flink 状态&#xff08;State&#xff09;简介 在流式计算中有些操作一次处理一个独立的事件(比如解析一个事件), 有些操作却需要记住多个事件的信息(比如窗口操作)。那些需要记住多个事件信息的操作就是有状态的。流式计算分为无状态计算和有状态计算两种情况。状态可以理…

Word题库转Excel关键字快速查询题库

一、前言 内部培训会有Word版本题库&#xff0c;考核时如果使用Word、Excel、PDF等文档进行关键字查询题目体验不佳。so&#xff0c;撸个软件吧&#xff01;   20240728更新&#xff1a;支持更多题库类型。 二、Word题库转Excel 1、Word题库格式要求 内容格式要求事例题目…

在 Postman 中设置全局 token

目录 问题描述解决方案 问题描述 在使用 Postman 进行接口测试时&#xff0c;经常会遇到在 Header 中添加 token 的情况。当接口数量较多时&#xff0c;需要为每个接口进行设置&#xff0c;而且当 token 失效时需要重新获取并设置&#xff0c;这样一来效率较低。 解决方案 下…

wpf中开发独立模块功能和左侧1个菜单的框架演示

此篇文章适用于有一定经验的wpf开发者&#xff0c;并且是团队协作开发模式&#xff0c;并且业务与此比较相近的话&#xff0c;用起来非常的方便。 我们在开发wpf程序的时候&#xff0c;比如1&#xff0c;2个人&#xff0c;那肯定随便怎么开发&#xff0c;都没事&#xff0c;代码…

Matlab M_map工具箱绘制Interrupted Mollweide Projection

GMT自带了许多的地图投影&#xff0c;但是对于Interrupted Mollweide投影效果却不好。 作为平替的m_map工具箱中带有的投影类型可完美解决这一问题。 Interrupted Mollweide Projection长这样 全球陆地 全球海洋 使用Matlab工具箱m_map展示全球海平面变化的空间分布 addpath(…

【Dart 教程系列第 49 篇】什么是策略设计模式?如何在 Dart 中使用策略设计模式

这是【Dart 教程系列第 49 篇】&#xff0c;如果觉得有用的话&#xff0c;欢迎关注专栏。 博文当前所用 Flutter SDK&#xff1a;3.22.1、Dart SDK&#xff1a;3.4.1 文章目录 一&#xff1a;什么是策略设计模式&#xff1f;二&#xff1a;为什么要使用策略设计模式&#xff1…

UG NX2406 安装教程

软件介绍 UG是一个交互式CAD/CAM(计算机辅助设计与计算机辅助制造)系统&#xff0c;它功能强大&#xff0c;可以轻松实现各种复杂实体及造型的建构。 它在诞生之初主要基于工作站&#xff0c;但随着PC硬件的发展和个人用户的迅速增长&#xff0c;在PC上的应用取得了迅猛的增长…

西蒙学习法

西蒙学习法 一根筋&#xff0c;挖死坑&#xff1b;会思考&#xff0c;持续不断的思考&#xff1b;会问问题&#xff0c;有深度的问题&#xff1b;一直想一个问题的解决办法&#xff1b; 资料 《世界十大学习方法》之西蒙学习法

【HarmonyOS】应用推送使用个推SDK如何实现?

【HarmonyOS】应用推送使用个推SDK如何实现&#xff1f; 前言 个推和极光都是市面上很成熟的推送第三方SDK了。今天讲讲个推SDK在鸿蒙中如何集成使用。 存在即合理&#xff0c;三方SDK推送给我们带来了极大的好处&#xff0c;首先在服务器后台处理一套API就可搞定&#xff0…

Matlab 命令行窗口默认输出(异常)

目录 前言Matlab 先验知识1 异常输出的代码2 正常输出的代码 前言 在单独调试 Matlab 写的函数时出现不想出现的异常打印值&#xff0c;逐个注释排查才找到是 if elseif else 代码块的问题&#xff0c;会默认打印输出 else 部分第一个返回值的值&#xff08;下方代码中的 P值&…

基于jeecgboot-vue3的Flowable流程仿钉钉流程设计器-抄送服务处理

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、因为仿钉钉设计器里抄送人是一个服务任务&#xff0c;所以要根据这个服务任务进行处理 2、前端就是一个抄送&#xff0c;选择人 3、这里用了jeecg的选择人组件 <el-form-item prop…

昇思25天学习打卡营第10天|xiaoyushao

从今天开始做一些实践应用&#xff0c;今天分享的是FCN图像语义分割。 全卷积网络&#xff08;Fully Convolutional Networks&#xff0c;FCN&#xff09;是UC Berkeley的Jonathan Long等人于2015年在Fully Convolutional Networks for Semantic Segmentation一文中提出的用于图…

培养前端工程化思维,不要让一行代码毁了整个程序

看《阿丽亚娜 5 号&#xff08;Ariane 5&#xff09;火箭爆炸》有感。 1、动手写项目之前&#xff0c;先进行全局性代码逻辑思考&#xff0c;将该做的事情&#xff0c;一些细节&#xff0c;统一建立标准&#xff0c;避免为以后埋雷。 2、避免使用不必要或无意义的代码、注释。…