登录

  • 登录
  • 忘记密码?点击找回

注册

  • 获取手机验证码 60
  • 注册

找回密码

  • 获取手机验证码60
  • 找回
毕业论文网 > 外文翻译 > 计算机类 > 计算机科学与技术 > 正文

燃气表运行监管系统之计费管理的设计与实现外文翻译资料

 2022-08-24 11:08  

1.4.1. Dependency Injection

Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern.

Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.

DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection.

Constructor-based Dependency Injection

Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection:

Java

Kotlin

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on a MovieFinder

private MovieFinder movieFinder;

// a constructor so that the Spring container can inject a MovieFinder

public SimpleMovieLister(MovieFinder movieFinder) {

this.movieFinder = movieFinder;

}

// business logic that actually uses the injected MovieFinder is omitted...

}

Notice that there is nothing special about this class. It is a POJO that has no dependencies on container specific interfaces, base classes or annotations.

Constructor Argument Resolution

Constructor argument resolution matching occurs by using the argumentrsquo;s type. If no potential ambiguity exists in the constructor arguments of a bean definition, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class:

Java

Kotlin

package x.y;

public class ThingOne {

public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {

// ...

}

}

Assuming that ThingTwo and ThingThree classes are not related by inheritance, no potential ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the lt;constructor-arg/gt; element.

lt;beansgt;

lt;bean id='beanOne' class='x.y.ThingOne'gt;

lt;constructor-arg ref='beanTwo'/gt;

lt;constructor-arg ref='beanThree'/gt;

lt;/beangt;

lt;bean id='beanTwo' class='x.y.ThingTwo'/gt;

lt;bean id='beanThree' class='x.y.ThingThree'/gt;

lt;/beansgt;

When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as lt;valuegt;truelt;/valuegt;, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class:

Java

Kotlin

package examples;

public class ExampleBean {

// Number of years to calculate the Ultimate Answer

private int years;

// The Answer to Life, the Universe, and Everything

private String ultimateAnswer;

public ExampleBean(int years, String ultimateAnswer) {

this.years = years;

this.ultimateAnswer = ultimateAnswer;

}

}

Constructor argument type matching

In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument by using the type attribute. as the following example shows:

lt;bean id='exampleBean' class='examples.ExampleBean'gt;

lt;constructor-arg type='int' value='7500000'/gt;

lt;constructor-arg type='java.lang.String' value='42'/gt;

lt;/beangt;

Constructor argument index

You can use the index attribute to specify explicitly the index of constructor arguments, as the following example shows:

lt;bean id='exampleBean' class='examples.ExampleBean'gt;

lt;constructor-arg index='0' value='7500000'/gt;

lt;constructor-arg index='1' value='42'/gt;

lt;/beangt;

In addition to resolving the ambiguity of

剩余内容已隐藏,支付完成后下载完整资料


1.4.1.依赖注入

依赖注入(DI)是一个过程,通过该过程,对象只能通过构造函数参数,工厂方法的参数或在构造或创建对象实例后在对象实例上设置的属性来定义其依赖关系(即,与它们一起工作的其他对象)或者从工厂方法返回。此时,容器在创建bean时注入那些依赖项。从根本上讲,此过程是通过使用类的直接构造或服务定位器模式来控制bean自身依赖关系的实例化或位置的bean本身的逆过程(因此称为控制反转)。

使用DI原理,代码更加简洁,当为对象提供依赖项时,去耦会更有效。该对象不查找其依赖项,也不知道依赖项的位置或类。结果就是,你的类变得更易于测试,尤其是当依赖项依赖于接口或抽象基类时,它们允许在单元测试中使用存根或模拟实现。

DI存在两个主要变体:基于构造函数的依赖注入基于Setter的依赖注入

基于构造函数的依赖注入

基于构造函数的DI是通过容器调用具有多个参数(每个参数代表一个依赖项)的构造函数来完成的。调用static带有特定参数的工厂方法来构造Bean几乎是等效的,并且本次讨论将构造函数和static工厂方法的参数视为类似。以下示例显示了只能通过构造函数注入进行依赖项注入的类:

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on a MovieFinder

private MovieFinder movieFinder;

// a constructor so that the Spring container can inject a MovieFinder

public SimpleMovieLister(MovieFinder movieFinder) {

this.movieFinder = movieFinder;

}

// business logic that actually uses the injected MovieFinder is omitted...

}

注意,该类没有什么特别的。它是一个POJO,不依赖于特定于容器的接口,基类或注释。

构造函数参数解析

构造函数参数解析匹配通过使用参数的类型进行。如果Bean定义的构造函数参数中不存在潜在的歧义,则在实例化Bean时,Bean定义中定义构造函数参数的顺序就是将这些参数提供给适当的构造函数的顺序。考虑以下类别:

package x.y;

public class ThingOne {

public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {

// ...

}

}

假设ThingTwo和ThingThree类不是通过继承关联的,则不存在潜在的歧义。因此,以下配置可以正常工作,并且你无需在lt;constructor-arg/gt;元素中显式指定构造函数参数索引或类型。

lt;beansgt;

lt;bean id='beanOne' class='x.y.ThingOne'gt;

lt;constructor-arg ref='beanTwo'/gt;

lt;constructor-arg ref='beanThree'/gt;

lt;/beangt;

lt;bean id='beanTwo' class='x.y.ThingTwo'/gt;

lt;bean id='beanThree' class='x.y.ThingThree'/gt;

lt;/beansgt;

当引用另一个bean时,类型是已知的,并且可以发生匹配(与前面的示例一样)。当使用诸如此类的简单类型时lt;valuegt;truelt;/valuegt;,Spring无法确定值的类型,因此在没有帮助的情况下无法按类型进行匹配。考虑以下类别:

package examples;

public class ExampleBean {

// Number of years to calculate the Ultimate Answer

private int years;

// The Answer to Life, the Universe, and Everything

private String ultimateAnswer;

public ExampleBean(int years, String ultimateAnswer) {

this.years = years;

this.ultimateAnswer = ultimateAnswer;

}

}

构造函数参数类型匹配

在上述情况下,如果通过使用type属性显式指定构造函数参数的类型,则容器可以使用简单类型的类型匹配。如以下示例所示:

lt;bean id='exampleBean' class='examples.ExampleBean'gt;

lt;constructor-arg type='int' value='7500000'/gt;

lt;constructor-arg type='java.lang.String' value='42'/gt;

lt;/beangt;

构造函数参数索引

你可以使用该index属性来明确指定构造函数参数的索引,如以下示例所示:

lt;bean id='exampleBean' class='examples.ExampleBean'gt;

lt;constructor-arg index='0' value='7500000'/gt;

lt;constructor-arg index='1' value='42'/gt;

lt;/beangt;

除了解决多个简单值的歧义性之外,指定索引还可以解决歧义,其中构造函数具有两个相同类型的参数。索引从0开始。

构造函数参数名称

你还可以使用构造函数参数名称来消除歧义,如以下示例所示:

lt;bean id='exampleBean' class='examples.ExampleBean'gt;

lt;constructor-arg name='years' value='7500000'/gt;

lt;constructor-arg name='ultimateAnswer' value='42'/gt;

lt;/beangt;

请记住,要立即使用该功能,必须在启用调试标志的情况下编译代码,以便Spring可以从构造函数中查找参数名称。如果你不能或不希望使用debug标志编译代码,则可以使用@ConstructorPropertiesJDK注释显式命名构造函数参数。然后,样本类必须如下所示:

package examples;

public class ExampleBean {

// Fields omitted

@ConstructorProperties({'years', 'ultimateAnswer'})

public ExampleBean(int years, String ultimateAnswer) {

this.years = years;

this.ultimateAnswer = ultimateAnswer;

}

}

基于Setter的依赖注入

基于设置器的DI是通过在调用无参数构造函数或无参数static工厂方法以实例化你的bean之后,在你的bean上调用setter方法来完成的。

下面的示例显示只能通过使用纯setter注入来依赖注入的类。此类是常规的Java。它是一个POJO,不依赖于容器特定的接口,基类或注释。

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on the MovieFinder

private MovieFinder movieFinder;

// a setter method so that the Spring container can inject a MovieFinder

public void setMovieFinder(MovieFinder movieFinder) {

this.movieFinder = movieFinder;

}

// business logic that actually uses the injected MovieFinder is omitted...

}

将ApplicationContext支持基于构造函数和基于setter的DI为它所管理的beans。在已经通过构造函数方法注入了某些依赖项之后,它还支持基于setter的DI。你可以以的形式配置依赖项,将BeanDefinition其与PropertyEditor实例结合使用以将属性从一种格式转换为另一种格式。但是,大多数Spring用户并不直接(即以编程方式)使用这些类,而是使用XMLbean定义,带注释的组件(即带有@Component,@Controller等等的类)或@Bean基于Java的@Configuration类中的方法。然后将这些源在内部转换为的实例,BeanDefinition并用于加载整个SpringIoC容器实例。

基于构造函数或基于setter的DI?

由于可以混合使用基于构造函数的DI和基于setter的DI,因此,将构造函数用于强制性依赖项,将setter方法或配置方法用于可选性依赖项是一个很好的经验法则。请注意,可以在setter方法上使用

您需要先支付 30元 才能查看全部内容!立即支付

企业微信

Copyright © 2010-2022 毕业论文网 站点地图