使用Java 8.0进行类型安全的依赖项注入

所以我有时真的很想念旧学校的依赖注入。 当Spring仍然“轻量级”时,我们很高兴地使用“ 一天学习 ” Spring bean xml配置在application.xml文件中配置了所有bean。 缺点当然是类型安全性的损失。 我可以想到很多测试用例,这些用例的唯一目的是引导Spring配置文件,并且只是看看ApplicationContext是否由于接线错误和所包含的bean xml配置文件的正确解析而启动而不会引起麻烦。

我可能是少数,但我从未喜欢过Spring Schema配置。 在我看来,配置有点像配置。


随之而来的是注释,并进行了改进,但需要注意的是,您必须为所有这些注释导入库。 我喜欢注释,但是将所有DI信息放在一个中央位置是一个很好的情况,这样您就可以实际看到您的应用程序如何挂在一起。 最后,有时您需要创建无法注释的托管对象。

Java Spring配置通过编译时安全性使事情变得更好,但是我不得不重新考虑我做大量接线的方式,因为当我丢失了一些懒惰的评估时,我不得不小心地进行接线。 Spring上下文作为Java代码在ApplicationContext启动时立即评估。

因此,基于Java的DI很不错,但是我们如何使用Java 8.0进行改进呢?

应用那个Lambda Hammer

正确,所以这是开始在Java 8.0中应用新锤子的文章的一部分: Lambdas 。

首先,Lambda提供了一种安全的方式来推迟执行直到需要时。

因此,让我们首先创建一个称为“ ObjectDefinition”的包装对象,该对象的工作是定义如何创建对象并使用各种值进行连接。 它通过实例化要创建的类和对象来工作(在这种情况下,我们有一个名为“ MyObject ”的类)。 我们还为它提供了映射到特定值的java.util.function.BiConsumer接口的列表。 该列表将用于执行在对象上设置值的实际任务。

然后,ObjectDefintion使用正反射实例化对象,然后通过BiConsumer接口列表运行,传递具体对象的实例和映射的值。

假设我们为ObjectDefinition提供了流畅的DSL,我们可以通过添加set()方法来定义对象,该方法采用BiConsumer和要设置的值并填充BiConsumer列表,如下所示:

MyObject result = new ObjectDefinition() .type(MyObject.class).set((myObject, value)-> myObject.setA(value), "hello world").set((myObject, value)-> myObject.setB(value), "hallo welt").create();

create()方法仅实例化MyObject实例,然后遍历BiConsumers列表,并通过映射值调用它们。

(好金田)

现在,Java 8.0中的另一个有趣的功能是方法引用,该功能是编译器将方法包装在功能接口中的功能,条件是该方法可以映射到该功能接口的签名。

方法引用允许您映射到对象的任意实例,前提是该方法的第一个参数是该实例值,且后续参数与其参数列表匹配。

这使我们能够将BiConsumer映射到setter,其中第一个参数是目标实例,第二个参数是传递给setter的值:

MyObject result = new ObjectDefinition().type(MyObject.class).set(MyObject::setA, "hello world").set(MyObject::setB, "hallo welt").create();

方法引用提供了一个有趣的功能,因为它提供了一种以完全类型安全的方式将引用传递给方法的方法。 所有示例都需要设置正确的类型和值,并且setter方法需要与该类型相对应。

现在是集装箱时间

因此,现在我们有了一个不错的用于构建对象的小DSL,但是如何将其粘贴到容器中并允许我们的ObjectDefinition注入对其他值的引用呢?

好吧,假设我们有这个容器,它方便地提供了一个build()方法,该方法提供了一个添加新ObjectDefinition的钩子。

现在,我们有了一个容器,可以用来在该容器中注入不同的对象:

Container container = create((builder) -> {builder.define(MyObject.class).set(MyObject::setA, "hello world");});String myString = container.get(MyObject.class);

我们的Container对象具有define()方法,该方法创建ObjectDefinition的实例,然后该实例用于定义如何创建对象。

但是依赖项呢?

如果不能注入依赖项,则依赖注入是没有乐趣的,但是由于有了容器,我们现在可以引用容器中的其他对象。

为此,我们将inject()方法添加到我们的ObjectDefinition类型,然后可以使用该类型来引用容器中的另一个对象:

Container container = create((builder) -> {builder.define(String.class).args("hello world");builder.define(MyObject.class).inject(MyObject::setA,String.class);});MyObject myString = container.get(MyObject.class);

在此示例中,我们映射了另一个String类型的对象这里的args()方法是可以将值映射到对象的构造函数的方法)。 然后,我们调用inject()方法注入此String。

生命周期。

我们可以使用Lambda和方法引用的相同方法来管理容器中对象的生命周期。

假设我们要在设置所有值之后运行初始化方法,我们只需添加一个新的Functional接口,然后在设置所有值之后调用该接口。

在这里,我们使用java.util.function.Consumer接口,其中参数是我们要调用初始化代码的实例。

Container container = create((builder) -> {builder.define(MyObject.class).set(MyObject::setA,"hello world").initWith(MyObject::start);});MyObject myString = container.get(MyObject.class);

在此示例中,我们向MyObject类添加了一个start()方法。 然后将其作为消费者通过initWith()方法传递给ObjectDefinition。

另一个依赖注入容器

因此,所有这些技术(和更多)被包括在YADI集装箱,它表示Y诺特尔d ependancy njectionÇontainer。

  • 可以在Github上找到该代码,网址为https://github.com/jexenberger/yadi 。 并且根据Apache许可获得许可。

翻译自: https://www.javacodegeeks.com/2014/06/type-safe-dependency-injection-using-java-8-0.html

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

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

相关文章

a标签点击跳转失效--IE6、7的奇葩bug

一般运用a标签包含img去实现点击图片跳转的功能,这是前端经常要用到的东西。 今天遇到个神奇的bug:如果在img上再包裹一层div,而且div设置了width和height,则图片区域点击时,无任何响应。 出现这个bug的条件是&#…

python 数据类型之间的转换

Number数据类型转换 # ###强制类型换 Number (int float bool complex) var1 68 var2 6.89 var3 False var4 3-4j var5 "12345678" var6 "qwe123"#(1) int 强制转换成整型 res int(var2) res int(var3) #res int(var4) #TypeError: cant convert …

php构造数组,并把多数组插入php文件

晚上做的一点东西&#xff0c;发出来大家共享下&#xff01; Code<?php //php 链接数据库mysql_connect("localhost", "root", "hicc") or die("Could not connect: " . mysql_error());mysql_select_db("babyker");$re…

针对新手的Java EE7和Maven项目–第6部分

从前面的部分恢复 第1 部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分 &#xff0c; 第4 部分 &#xff0c; 第5部分 在上一篇文章&#xff08;第5部分&#xff09;中&#xff0c;我们发现了如何使用Arquillian&#xff08;我们的EJB服务&#xff09;进行单元测试&#xf…

1. 整除及其性质

整除的定义&#xff1a; 若整数 a 除以非零整数 b &#xff0c;商为整数且余数为零&#xff0c;即 a 能被 b 整除&#xff0c;记做 b | a&#xff0c;读作&#xff1a;b 整除 a 或 a 能被 b 整除。a 叫做 b 的倍数&#xff0c; b 叫做 a 的因数。 整除基本性质&#xff1a; 1. …

echarts 地图 免费离线js,json包分享

最近&#xff0c;项目中需要用到地图&#xff0c;由于项目的特殊性&#xff0c;只能使用内网获取数据。 然而&#xff0c;echarts官网上的离线地图包&#xff08;http://echarts.baidu.com/download-map.html&#xff09;早在一年前就不支持下载了&#xff0c;推荐使用地图API…

WPF 中的设备无关单位

WPF窗体以及内部的所有元素都是采用设备无关的单位来衡量的。一个设备无关单位定义为1英寸的96分之一&#xff0c;即1/96 inch。 假定我们创建了一个WPF按钮&#xff0c;其大小为96x96个单位&#xff0c;如果使用标准Windows的DPI设置&#xff08;96dpi&#xff09;&#xff0…

收藏网站制作常用经典css.div.布局.设计实例打包下载(下方有其他链接)

http://www.aa25.cn/234.shtml 转载于:https://www.cnblogs.com/asia/archive/2009/05/20/1467772.html

Java 8 Friday:大多数内部DSL已过时

在Data Geekery &#xff0c;我们喜欢Java。 而且&#xff0c;由于我们真的很喜欢jOOQ的流畅的API和查询DSL &#xff0c;我们对Java 8将为我们的生态系统带来什么感到非常兴奋。 Java 8星期五 每个星期五&#xff0c;我们都会向您展示一些不错的教程风格的Java 8新功能&#…

Starter pom

以下图片是引用书籍内容&#xff1a; 比如你在用boot写一个web项目&#xff0c;在maven中你会导入&#xff1a; <!-- 导入spring boot的web支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-we…

上传图片截图预览控件不显示cropper.js 跨域问题

上传图片到图片服务器&#xff0c;因为域名不同&#xff0c;多以会有跨域问题。 No Access-Control-Allow-Origin header is present on the requested resource. Origin http://img.xxx.com is therefore not allowed access. 照看代码发现&#xff0c;cropper.js里面对图片的…

在Spring JDBC中添加C3PO连接池

连接池是一种操作&#xff0c;其中系统会预先初始化将来要使用的连接。 这样做是因为在使用时创建连接是一项昂贵的操作。 在本文中&#xff0c;我们将学习如何在Spring JDBC中创建C3P0连接池&#xff08;某人未使用休眠&#xff09;。 Pom.xml <dependency><groupI…

在 CentOS/Fedora 下安装 JAVA 环境

介绍 本文介绍如何在 CentOS 7&#xff08;6/6.5&#xff09;、 Fedora、RHEL 上安装 Java。Java是一个流行的软件平台&#xff0c;允许您运行Java应用程序。 本文涵盖了以下Java版本的安装&#xff1a; OpenJDK 8Oracle Java 8先决条件 在开始之前&#xff0c;您应该有一个能够…

小程序: 在同一个文件夹中配置多个页面

1. 可以在同一个文件夹中配置多个页面&#xff08;即相关的放在一个文件夹中&#xff09; 如&#xff1a; 创建一个首页&#xff1a; 在 app.json中配置 -- pages/index/index创建一个首页中的相关页面&#xff1a; 在 app.json中配置 -- pages/index/detail/detail 博客地址…

[欧拉函数] Bzoj P2186 沙拉公主的困惑

Description 大富翁国因为通货膨胀&#xff0c;以及假钞泛滥&#xff0c;政府决定推出一项新的政策&#xff1a;现有钞票编号范围为1到N的阶乘&#xff0c;但是&#xff0c;政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现…

象素图和向量图

象素图和向量图主要的区别是动态和静态的区别 象素图是固定的图&#xff0c;它在图形生成时就已经是由固定的象素点组成了&#xff0c;不可以再变化&#xff0c;所以大小不一样&#xff0c;清晰度不一样&#xff0c; 向量图是动态的图&#xff0c;每次显示都会根据大小绘制本身…

ActiveMQ –经纪人网络解释–第5部分

在前面的第4部分中&#xff0c;我们已经看到了如何使用网络连接器在队列中平衡远程使用者的负载。 在第5部分中&#xff0c;我们将看到如果在某个主题上有并发远程持久订阅者&#xff0c;则相同的配置将如何工作。 考虑以下配置…。 图1&#xff1a;经纪人网络–主题上的负载…

Unity项目导入的error

5.6.3error 如下&#xff1a;An assembly with the same name UnityEngine.UI has already been imported. Consider removing one of the references or sign the assemblyanswer:I deleted all the c# project files at the root of the folder structure and reloaded the p…

小程序: 域名配置

1. 问题 在小程序中&#xff0c;如果我们没有在微信公众平台: 配置 https开头的、备案过的域名话&#xff0c;调用该域名下的接口&#xff0c;就会报错 当然&#xff1a; 如果只是简单的学习下小程序使用的话&#xff0c;可以不校验域名 — 微信开发者工具中&#xff1a; 详情 …

描述符

描述符描述符也是面向进阶的一种&#xff0c;由于它的涉及比较广&#xff0c;所以单独讲。 一、描述符 描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议。 描述符的作用是用来代理另外一个类的属性&#xf…