spring不自动下载_Spring:自动接线或不自动接线

spring不自动下载

自从使用Spring 2.5以来,我从基于XML的应用程序上下文切换到了注释。 尽管我发现那些非常有用且节省大量时间的人,但我始终觉得在灵活性方面我失去了一些东西。 特别是@Autowired批注-或标准@Inject-在我看来就像新的“新”,增加了我的类之间的联系,使在需要时更难更改实现。 我仍然有这种感觉,但是我已经学到了一种有趣的模式来限制测试代码时的问题,即当我想将bean的真实实现替换为模拟时。 让我们用一个例子来说明。 我想构建一个应用程序,以便为我在网络上找到有趣的东西。 我将从一个接受URL的服务开始,如果它是一个有趣的新服务,则将其添加书签。 直到最近,我可能已经编写了如下代码:

@Named
public class AwesomenessFinder {@Injectprivate BlogAnalyzer blogAnalyzer;@Injectprivate BookmarkService bookmarkService;public void checkBlog(String url) {if (!bookmarkService.contains(url) && blogAnalyzer.isInteresting(url)) {bookmarkService.bookmark(url);}}
}

不好,你明白为什么吗? 如果没有,请继续阅读,希望您今天能学到一些有用的东西。 因为我很认真,所以我想为此代码创建单元测试。 希望我的算法很好,但是我想确保它不会为无聊的博客添加书签或为相同的URL添加两次书签。 那就是问题所在,我想将AwesomenessFinder与它的依赖隔离开来。 如果我使用的是XML配置,则可以在测试上下文中简单地注入模拟实现,是否可以使用批注来实现? 嗯,是! 有一种方法,带有@Primary批注。 让我们尝试为BlogAnalyzer和BookmarkService创建模拟实现。

@Named
@Primary
public class BlogAnalyzerMock implements BlogAnalyzer {public boolean isInteresting(String url) {return true;}
}@Named
@Primary
public class BookmarkServiceMock implements BookmarkService {Set bookmarks = new HashSet();public boolean contains(String url) {return bookmarks.contains(url);}public void bookmark(String url) {bookmarks.add(url);}
}

因为我使用Maven并将这些模拟放置在test / java目录中,所以主应用程序将看不到它们,并将注入实际的实现。 另一方面,单元测试将看到2种实现。 @Primary是必需的,以防止出现类似以下的异常:

org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [service.BlogAnalyzer] is defined: expected single matching bean
but found 2: [blogAnalyzerMock, blogAnalyzerImpl]

现在,我可以测试我的算法了:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application-context.xml")
public class AwesomenessFinderTest {@Injectprivate AwesomenessFinder awesomenessFinder;@Injectprivate BookmarkService bookmarkService;@Testpublic void checkInterestingBlog_bookmarked() {String url = "http://www.javaspecialists.eu";assertFalse(bookmarkService.contains(url));awesomenessFinder.checkBlog(url);assertTrue(bookmarkService.contains(url));}
}

不错,我测试了幸福的道路,一个有趣的博客被加了书签。 现在我该如何测试其他情况。 当然,我可以在模拟中添加一些逻辑,以查找某些已经添加了书签或不感兴趣的URL,但这会变得笨拙。 这是一个非常简单的算法,想象一下测试更复杂的东西有多糟糕。 有一种更好的方法需要重新设计我的类以及注入依赖项的方法。 方法如下:

@Named
public class AwesomenessFinder {private BlogAnalyzer blogAnalyzer;private BookmarkService bookmarkService;@Injectpublic AwesomenessFinder(BlogAnalyzer blogAnalyzer, BookmarkService bookmarkService) {this.blogAnalyzer = blogAnalyzer;this.bookmarkService = bookmarkService;}public void checkBlog(String url) {if (!bookmarkService.contains(url) && blogAnalyzer.isInteresting(url)) {bookmarkService.bookmark(url);}}
}

请注意,我仍然使用@Inject注释自动关联我的依赖项,因此AwesomenessFinder的调用者不会受到影响。 例如,客户端类中的以下内容仍然有效:

@Inject
private AwesomenessFinder awesomenessFinder;

但是,最大的不同是我在构造函数级别自动装配,这为我提供了一种注入模拟实现的干净方法。 而且,由于我们是在模拟,所以我们使用一个模拟库。 去年,我写了一篇有关嘲讽的文章,其中我使用了丑陋的二传手来注入嘲讽。 有了这里提到的技术,我不再需要暴露依赖项,我得到了更好的封装。 这是更新后的测试用例的样子:

public class AwesomenessFinderTest {@Testpublic void checkInterestingBlog_bookmarked() {BookmarkService bookmarkService = mock(BookmarkService.class);when(bookmarkService.contains(anyString())).thenReturn(false);BlogAnalyzer blogAnalyzer = mock(BlogAnalyzer.class);when(blogAnalyzer.isInteresting(anyString())).thenReturn(true);AwesomenessFinder awesomenessFinder = new AwesomenessFinder(blogAnalyzer, bookmarkService);String url = "http://www.javaspecialists.eu";awesomenessFinder.checkBlog(url);verify(bookmarkService).bookmark(url);}
}

请注意,现在这是纯Java语言,无需使用Spring注入模拟。 而且,这些模拟的定义与它们的用法位于同一位置,从而简化了维护。 为了更进一步,让我们实现其他测试用例。 为了避免代码重复,我们将重构测试类并引入一些枚举,以使测试用例尽可能地具有表达力。

public class AwesomenessFinderTest {private enum Knowledge {KNOWN, UNKNOWN};private enum Quality {INTERESTING, BORING};private enum ExpectedBookmark {STORED, IGNORED}private enum ExpectedAnalysis {ANALYZED, SKIPPED}@Testpublic void checkInterestingBlog_bookmarked() {checkCase(Knowledge.UNKNOWN, Quality.INTERESTING,ExpectedBookmark.STORED, ExpectedAnalysis.ANALYZED);}@Testpublic void checkBoringBlog_ignored() {checkCase(Knowledge.UNKNOWN, Quality.BORING,ExpectedBookmark.IGNORED, ExpectedAnalysis.ANALYZED);}@Testpublic void checkKnownBlog_ignored() {checkCase(Knowledge.KNOWN, Quality.INTERESTING,ExpectedBookmark.IGNORED, ExpectedAnalysis.SKIPPED);}private void checkCase(Knowledge knowledge, Quality quality,ExpectedBookmark expectedBookmark, ExpectedAnalysis expectedAnalysis) {BookmarkService bookmarkService = mock(BookmarkService.class);boolean alreadyBookmarked = (knowledge == Knowledge.KNOWN) ? true : false;when(bookmarkService.contains(anyString())).thenReturn(alreadyBookmarked);BlogAnalyzer blogAnalyzer = mock(BlogAnalyzer.class);boolean interesting = (quality ==  Quality.INTERESTING) ? true : false;when(blogAnalyzer.isInteresting(anyString())).thenReturn(interesting);AwesomenessFinder awesomenessFinder = new AwesomenessFinder(blogAnalyzer, bookmarkService);String url = "whatever";awesomenessFinder.checkBlog(url);if (expectedBookmark == ExpectedBookmark.STORED) {verify(bookmarkService).bookmark(url);} else {verify(bookmarkService, never()).bookmark(url);}if (expectedAnalysis == ExpectedAnalysis.ANALYZED) {verify(blogAnalyzer).isInteresting(url);} else {verify(blogAnalyzer, never()).isInteresting(url);}}
}

最后但并非最不重要的一点是,构造函数注入的一个不错的好处是能够将类的所有依赖项放在同一位置(构造函数)。 如果依赖项列表超出了控制范围,则构造函数的大小会产生非常明显的代码味道。 这表明您在班级中肯定承担了多个责任,您应该将其划分为多个班级,以便于单元测试更容易地隔离。

参考: 可以通过编程和更多博客上的JCG合作伙伴 Damien Lepage 自动连线或不自动 连线 。

翻译自: https://www.javacodegeeks.com/2013/04/spring-to-autowire-or-not-to-autowire.html

spring不自动下载

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

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

相关文章

php faker 中文,使用faker 生成中文测试数据

https://github.com/fzaninotto/Faker/blob/master/src/Faker/Provider/zh_CN/Address.php常用的类型都在里面。下面是一个实例。使用了laravel 框架的工厂模式向数据库填充测试数据。$factory->define(App\Models\Customer::class, function ($faker) {$faker Faker\Facto…

python课设总结_Python技术分享课总结:用Python模拟知乎自动登录

原标题:Python技术分享课总结:用Python模拟知乎自动登录Python语言是由Guido van Rossum大牛在1989年发明,它是当今世界最受欢迎的计算机编程语言之一,也是一门“学了有用、学了能用、学会能久用”的计算生态语言。为此&#xff0…

Spring MVC中@RequestParam和@PathVariable批注之间的区别?

Spring MVC框架是在Java世界中开发Web应用程序最流行的框架之一,它还提供了一些有用的注释,可以从传入的请求中提取数据并将请求映射到控制器,例如 RequestMapping, RequestParam和PathVariable。 即使将RequestParam和ParthVari…

php 随机钱数,PHP 仿微信红包金额随机

博主寒冰最近闲来无事。就想研究一下微信红包的金额随机算法。早在微信红包刚出来的时候就研究过。始终不得要领。后来,通过查阅诸多资料。听说要实现“正态分布”。这个理论的东西不想深挖。恰好在网上一篇博客找到一个相对完整的算法。我经过试用确实不错。经过我…

excel 两列模糊匹配给出结果_北大硕士给大脑植入Excel病毒,工作效率提升了好几倍...

在工作中,我们经常会碰到这样的同事,他们是这样完成工作的:先用计算器算好结果,甚者动用手指头在电脑屏幕上数数,然后把数据填写到Excel表格中。结果可以预见,原本可以在上班时间完成的工作,愣是…

5 在java等于多少,java基础面试题之Java中的Math. round(-1. 5)等于多少

Java 中的 Math. round(-1. 5) 等于多少?答案:-1/*** Returns the closest {code long} to the argument, with ties* rounding to positive infinity.** Special cases:* If the argument is NaN, the result is 0.* If the argument is negative infin…

java ee cdi_Java EE CDI Producer方法教程

java ee cdi这是CDI Producer方法的教程。 在CDI中,生产者方法生成一个对象,然后可以将其注入。 当我们要注入本身不是bean的对象,要注入的对象的具体类型在运行时可能有所不同,或者当对象需要一些bean构造函数不执行的自定义初始…

qnap nas web php,如何在QNAP NAS上建立并使用 iSCSI Target

本帖最后由 小Q 于 2015-2-5 13:30 编辑在QNAP Turbo NAS上建立并使用iSCSI Target,快速、便利且便宜建置网络储存系统之方式内容:l 在Windows中使用Microsoft iSCSI启动器来连接iSCSI装置什么是iSCSI且它有什么好处?iSCSI(Internet Small Computer Sy…

python坐标轴刻度设置对数_Python中的对数刻度

我试图以对数比例(Y轴)绘制一个图形,但我需要在Y轴上显示原始值。我用了密码:# -*- coding: utf-8 -*-import mathimport matplotlib.pyplot as pltimport matplotlib.dates as datesfrom datetime import datetime, timedeltaimport numpy as npx []y …

openssl php api,PHP7使用openssl解密易班API中的用户数据

PHP7使用openssl解密易班API中的用户数据一、mcrypt扩展解密自从PHP版本更新到了7.1以上以后,mcrypt扩展被废弃,使用mcrypt扩展会出现如下图的报错。只能使用openssl来代替。然而易班轻应用提供的还是旧版本的mcrypt扩展,这将导致php版本升级…

Spring MVC的DispatcherServlet – Java开发人员应该知道的10件事

如果您使用过Spring MVC,那么您应该知道什么是DispatcherServlet? 它实际上是Spring MVC的心脏,确切地说是MVC设计模式或控制器的C语言。 应该由Spring MVC处理的每个Web请求都通过DispatcherServlet处理。 通常,它是Front Contro…

python123第七章_Python入门第7/10页

Python入门第7/10页更新时间:2007年02月08日 00:00:00 作者:第七章 输入输出有几种办法可以从程序输出;数据可以用可读的形式显示,或保存到文件中以备日后使用。本章讨论一些输入输出的办法。7.1 输出格式控制到现在为止我们已经…

运行时错误7内存溢出_分别从运行时和GC的角度看JAVA8内存管理

运行时区域1.程序计数器程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机概念模型里(概念模型,各种虚拟机可能会通过一些更高效的方式实现&#…

php baocuo error,PHP编译报错configure: error: Cannot find libmysqlclient under /usr.

今天编译PHP的时候遇到了几个错误,记录一下第一次编译的时候报错如下:configure: error: mcrypt.h not found. Please reinstall libmcrypt.报这个错是因为没有安装libmcrypt这个包,下载地址如下:wget ftp://mcrypt.hellug.gr/pub…

dart和python哪个好_RedMonk 2020 年 Q1 编程语言排行:Python 冲进前二,Dart 值得关注...

知名软件行业分析公司 RedMonk 发布了 2020 年第一季度编程语言排行榜。RedMonk 编程语言排行榜通过追踪编程语言在 GitHub 和 Stack Overflow 上的代码使用情况与讨论数量,统计分析后进行排序,其旨在深入了解潜在的语言采用趋势。该榜单一年发布两次&am…

jclouds_使用jclouds在S3上分段上传

jclouds1.目标 在上一篇文章中 ,我们研究了如何使用jclouds中的通用Blob API将内容上传到S3。 在本文中,我们将使用jclouds的S3特定的异步API上传内容并利用S3提供的分段上传功能。 2.准备 2.1。 设置自定义API 上传过程的第一部分是创建jclouds API-这…

mysql+表中公共信息,計算mysql中兩個表之間的公共行數

so heres my question...這是我的問題…Hi have two tables in mysql, called go_H and go_J, both looking like this:在mysql中有兩個表,叫做go_H和go_J,它們都是這樣的:go_Hgo_H---------------------------| gene | GoCode |-----------------------…

极域课堂管理系统软件如何取消控制_微缔电子组装业MES系统软件六大功能组成...

电子组装业MES系统软件六大功能组成MES系统软件是制造执行系统的英文简称,MES系统软件在整个企业信息集成系统中承上启下,是生产活动与管理活动信息沟通的桥梁,MES系统软件在产品从工单下发到生产成成品的整个过程中,扮演着促进生…

使用虚拟时间测试基于时间的反应堆堆芯流

Reactor Core实现了Reactive Streams规范,并处理了(可能无限的)数据流。 如果您感兴趣,请查看它提供的出色文档 。 在这里,我假设对Reactor Core库的Flux和Mono类型有一些基本的了解,并且将介绍Reactor Cor…

matlab二维数组排序函数,Matlab 用sort函数排序 二维数组

在Matlab中排序某个向量(一维)时,可以使用sort(A),其中A为待排序的向量,如果仅是用来排序A,那么直接使用sort(A)即可, 如果排序后还需要保留原来的索引可以用返回值,即[B,ind]sort(A),计算后&am…