mockito手动注入依赖
依赖注入是一种将行为与依赖解决方案分开的技术。 用简单的话来说,它使开发人员可以定义具有特定功能的类,这些功能取决于各种协作者,而不必定义如何获取对这些协作者的引用。 以此方式,实现了各个组件之间的解耦,并且通常引入了更简洁的代码。 更具体地说,一个组件仅列出必要的服务,而不是对依赖项进行硬编码,而在运行时,一个外部独立的组件将提供对这些服务的访问。 我们不应忘记,依赖注入只是控制反转的一种特殊形式,其中反转的关注点是获得所需依赖的过程。 前述技术的参考文章是Martin Fowler的 “控制容器的倒置和依赖注入模式” 。
为了注入依赖关系,已经出现了许多框架,最著名的是Spring和Guice (请参阅JavaCodeGeeks Spring相关文章)。 但是,对于小型项目使用整个框架无疑是一个过大的杀伤力。 我们的JCG合作伙伴之一, “ Death By Code”博客的作者,对如何手动处理依赖项注入做了简短的介绍 。 让我们看看他怎么说?
在另一篇文章中, “我真的需要单身人士吗?” ,我写了有关Singleton设计模式引入的问题的文章。 通过getInstance()方法访问单个唯一实例时,Singleton会变相充当全局变量,并引入紧密耦合和不必要的依赖关系。 我收到了读者的两个直接问题:
单例应该仅与依赖注入框架一起使用吗?
如果通过getInstance()访问Singleton创建紧密耦合,则通过new()创建任何其他类的实例也将导致紧密耦合。 那么,如何创建一个保持松散耦合的对象?
根据我的理解,依赖注入是这两个问题的答案。 但是,这并不要求使用框架。 依赖注入首先是一个概念,然后是一个框架。 当所讨论的应用程序很小时,我们总是可以通过手动注入依赖项来满足需求,而无需使用任何类似Spring的框架。
在任何Java应用程序中,我们都会反复遇到两个事件:
- 对象创建
- 对象之间的交互–业务逻辑
但是,通常我们将两者混为一谈,从而导致紧密耦合和不必要的依赖关系,这反过来又给维护以及单元测试带来麻烦。 让我尝试使用一个非常简单的示例来解释它:
class MyClass {
private A a; //A is an interface
private B b; //B is an interface
//Object creation within constructor
MyClass(A a, B b) {
a = new AImpl(); //AImpl is the concrete impl of A
b = new BImpl(); //BImpl is the concrete impl of B
}
//Application logic lies within this method
public void doSomething() {
//Do A specific thing
//Do B specific thing
C c = new CImpl(); //Object creation within the method.
//Do C specific thing
}
}
此类的问题是:
- 它无法将对象创建与业务逻辑分开,从而导致紧密耦合。
- 此处已完成了“实现编程”,而不是接口。 明天,如果需要A,B或C的不同实现,则必须更改类中的代码。
- 测试MyClass需要首先测试A,B,C。
让我尝试解决问题:
class MyClass {
private A a;
private B b;
private C c;
MyClass(A a, B b, C c) {
//Only Assignment
this.a = a;
this.b = b;
this.c = c;
}
//Application Logic
public void doSomething() {
//Do A specific thing
//Do B specific thing
//Do C specific thing
}
}
//The Factory
class MyFactory {
public MyClass createMyClass() {
return new MyClass(new AImpl(), new BImpl(), new CImpl());
}
}
class Main {
public static void main(String args[]) {
MyClass mc = new MyFactory().createMyClass();
mc.doSomething();
}
}
在这里已经实现了什么:
1.构造函数没有new():
没有在MyClass的构造函数中创建对象。 该构造函数仅用于字段(A,B,C)分配。 在这里,构造函数要求依赖项作为参数,但不创建它们(这是依赖项注入的最简单定义)。 但是,可以在构造函数中创建简单的Collection对象(如ArrayList,HashMap或value / leaf对象,如Person / Employee)(即应用程序内的对象,这些对象又不会创建其他对象)。 构造函数不应用于任何其他操作,例如I / O,线程创建等。
根据经验法则,任何对象都应仅保留对其直接完成工作所需的其他对象的引用(这称为Demeter法则)。 例如,如果MyClass需要其他称为X的类,则MyClass的构造函数应直接要求X。不应要求其他工厂F可以返回X的实例。违反“ Demeter法则”将导致不必要的依赖关系因此,如果您发现多个Dot(。)运算符,请当心-那里发生了非法事件。
2. Factory(MyFactory)负责对象的创建和连接:
所有新的操作员(90%-99%)应属于工厂。 它应负责为应用程序创建整个对象图,并应根据声明的依赖关系关联(连接)不同的对象(例如,MyClass需要A,B,C等)。 它不应包含任何其他内容-不应包含任何其他逻辑(没有I / O,线程创建等)。
明天如果C开始依赖于其他称为D的东西,则只会影响C和工厂,而不会影响整个对象图(C必须引入重载的构造函数,并且工厂必须合并对象实例化以及与对象接线相关的更改) 。
对于大型应用程序,当然可能会有多个工厂。 在这里,经验法则是一个工厂应该实例化具有相同寿命的所有对象。
3.对象的创建与业务逻辑是分开的:
MyClass现在是业务逻辑持有人。 它没有任何new()。 甚至,它也不了解用于业务逻辑的具体实现(即,它了解A,但不了解AImpl,即“接口程序而不是实现程序”)。
您一定已经开始认为我是在Singleton的背景下开始讨论的。 手动依赖项注入如何处理Singleton? 如何创建一个Singleton(减去紧密耦合,隐藏的依赖关系等)并在需要时访问它? 令人惊讶的是,我们的示例中已经有三个Singleton-AImpl,BImpl,CImpl。 如果工厂只负责创建Class的一个实例(通过仅调用new()一次),则其为Singleton。 是不是 然后,工厂可以将该依赖关系形式的唯一实例传递给需要它的所有其他对象。
4.那么,我们在哪里?
业务逻辑持有者MyClass的业务需要A,B和C。 它不会创建它们,而是要它们(依赖项)。 工厂(MyFactory)创建这些依赖关系并将其关联到MyClass。 但是,谁创造了工厂? 当然是主要方法(应用程序启动器:-)。 让我再重复一遍这个故事:main方法首先实例化工厂,工厂反过来实例化对象图,每个Object声明其依赖关系,最后main方法本身设置滚动-通过调用MyClass的doSomething()启动应用程序,即。 这些对象开始互相交谈,执行日常业务。
让我再重复一次: 创建工厂,使用工厂创建应用程序,然后启动应用程序! 对于大规模应用程序,可以通过像Spring,Google Guice等依赖注入框架来实现相同的目的。当然,它们还将带来许多其他好处。 但是,对于中小型应用程序,可以手动制作依赖项注入,从而使应用程序松散耦合,更易于维护并且当然对单元测试友好。
- 使用Spring AspectJ和Maven进行面向方面的编程
- JBoss 4.2.x Spring 3 JPA Hibernate教程
- GWT Spring和Hibernate进入数据网格世界
- 建立自己的GWT Spring Maven原型
- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程– Eclipse和Maven 2展示
- 使用Spring使用Java发送电子邮件– GMail SMTP服务器示例
翻译自: https://www.javacodegeeks.com/2010/12/dependency-injection-manual-way.html
mockito手动注入依赖