Spring 5.0.8.RELEASE文档 Core1-1.4.1 依赖注入

A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal.

一个典型的企业级应用不会由单一的对象所构成(Spring的叫法是bean)。甚至一些简单的应用也会拥有好几个对象相互协作,终端用户看起来是一致的应用。这个章节为你阐述怎么去组装多个bean来成为一个合作类从而去实现你的目标。

Dependency injection (DI) is a process whereby objects define their dependencies, that is, the other objects they work with, 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 (IoC), 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.

依赖注入(DI)是对象定义它们的依赖的处理过程,那就是原来是通过构造函数、工厂方法参数、属性set的方式设置好依赖对象,然后返回实例。现在是当bean创建的时候容器会自动注入这些依赖。所以整个过程被反转了,因此命名为控制反转(IoC),bean自身去控制实例以及其依赖通过明确构造函数类或者服务定位器模式。(应该是指bean实例化的配置-,-)

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 such, your classes become easier to test, in particular when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.

依赖注入使得代码干净和解耦,并使得对象设置它们的依赖更有效率。创建对象不用再去找和设置它的依赖,并且不用知道所依赖的class的位置和这个class的依赖。而且你的classes会变得更加易于测试。特别当依赖的class是接口或者抽象类,允许通过stub或mock的实现类方式进行单元测试。

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

DI主要存在于两个变体中,可以查看1.4.1章节。

第一种变体:
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. 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.

基于构造函数的依赖注入
基于构造函数的依赖注入已经非常成熟,它是通过调用构造函数,通过传入一个或多个参数来实现的依赖注入。有点类似于静态工厂方法实例化bean。清看下面例子:

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...
}

Constructor argument resolution
Constructor argument resolution matching occurs using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, then 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:

构造参数的解决办法
通过使用参数标签来解决,如果bean定义的构造器参数中没有潜在的歧义,那么在bean定义中定义构造器参数的顺序是当bean被实例化时,这些参数被提供给适当的构造函数的顺序。

package x.y;

public class Foo {

    public Foo(Bar bar, Baz baz) {
        // ...
    }
}

No potential ambiguity exists, assuming that Bar and Baz classes are not related by inheritance. Thus the following configuration works fine, and you do not need to specify the constructor argument indexes and/or types explicitly in the element.

假设Bar和Baz类与继承无关,则不存在潜在的歧义。因此,下面的配置可以很好地工作,您不需要在元素中显式地指定构造函数参数索引和/或类型。(自动根据类型匹配参数)

<beans>
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
    </bean>

    <bean id="bar" class="x.y.Bar"/>

    <bean id="baz" class="x.y.Baz"/>
</beans>

引起歧义的原因:例如当一个类中,包含有多个带参数构造器,而且构造器的参数数量和类型都一致,但是位置不同,这时如果通过构造器进行依赖注入的话,可能会造成参数歧义(错位传参)问题。

package com.main.autowrite.DI;

public class Customer {
    private String name;
    private String address;
    private int age;

    public Customer(String name, String address, int age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }

    public Customer(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    //getter and setter methods
    public String toString(){
        return " name : " +name + "\n address : "
               + address + "\n age : " + age;
    }
}

在bean.xml文件中的声明如下:

<bean id="customer" class="com.main.autowrite.DI.Customer">
    <constructor-arg>
        <value>jack</value>
    </constructor-arg>

    <constructor-arg>
        <value>1111111</value>
    </constructor-arg>

    <constructor-arg>
        <value>2222222</value>
    </constructor-arg>
  </bean>

测试方法以及结果:

@Test
    public void test(){
        ApplicationContext context = 
                new ClassPathXmlApplicationContext("com/main/autowrite/DI/bean.xml");

        Customer customer = 
                (Customer)context.getBean("customer");

        System.out.println(customer.toString());

    }

假设我们想要的是利用第二个构造函数进行传参,这时的运行结果就不是我们想要的,所以就产生了参数歧义的问题

目标结果为:
name : jack
address:2222222
age : 1111111

但是实际结果为:
name : jack
address:1111111
age : 2222222

这时,通过在bean.xml配置文件中对参数进行类型的限定,就可以达到我们的目标效果!!
修改如下:

<bean id="customer" class="com.main.autowrite.DI.Customer">
    <constructor-arg type="java.lang.String">
        <value>jack</value>
    </constructor-arg>

    <constructor-arg type="int">
        <value>1111111</value>
    </constructor-arg>

    <constructor-arg type="java.lang.String">
        <value>2222222</value>
    </constructor-arg>
  </bean>

就可以消除参数歧义的问题,从而使用目标构造器进行传参。所以还是建议配置好构造函数的参数类型。参考

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 true, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class:

当另一个bean被引用时,类型是已知的,并且可以发生匹配(就像前面的例子一样)。当使用一个简单的类型时,比如true,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;
    }
}

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 using the type attribute. For example:

构造参数匹配
根据上面的情节,如果您使用type属性显式地指定构造器参数的类型,那么容器可以使用与简单类型匹配的类型。例如:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

Constructor argument index
Use the index attribute to specify explicitly the index of constructor arguments. For example:

构造参数索引
使用index属性去明确指定参数在构造函数的位置。例如:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type. Note that the index is 0 based.

index索引这种方式除了解决多个简单值的模糊性之外,指定索引还解决了构造器有相同类型的两个参数的歧义。注意,索引是基于0的。

Constructor argument name
You can also use the constructor parameter name for value disambiguation:
构造参数name
你可以使用name属性去定义对应的构造函数参数name

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

Keep in mind that to make this work out of the box your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you can’t compile your code with debug flag (or don’t want to) you can use @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows:

请记住,如果你想要你的代码开箱即用,必须使用调试标记来编译,以便Spring能够从构造函数中查找参数名。如果您不能使用调试标志(或者不想)编译您的代码,那么您可以使用@ConstructorProperties JDK标注来显式地命名构造函数参数。然后,样本类必须如下所示:
(JDK中@ConstructorProperties的意思是如构造函数参数是(x , y) , 注释表明,构造函数的第一个参数可以用getX()方法检索,第二个参数与getY()方法一起检索。由于参数名在运行时通常是不可用的,所以没有注释,就没有办法知道参数是否与getX()和getY()或相反的方向一致。)
这个是使用构造函数name注入的方式时需要使用这个注解,或者在ide中Java Compiler配置允许把变量信息写入到class(应该就是类的构造函数参数是String a,变成class的时候也叫String a而不是String var1)参考

构造函数依赖注入有:根据type注入、根据name注入、根据index注入三种方式。

package examples;

public class ExampleBean {

    // Fields omitted

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}

Setter-based dependency injection
基于setter的依赖注入

Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean.

基于setter的依赖注入是通过容器去调用无参数的构造方法或者无参数的静态工厂方法创建的实例的setter方法完成的。

The following example shows a class that can only be dependency-injected using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes or annotations.

下面的例子展示纯粹的基于setter的依赖注入,下面的class传统的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...
}

The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (i.e., programmatically) but rather with XML bean definitions, annotated components (i.e., classes annotated with @Component, @Controller, etc.), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance.

ApplicationContext 上下文提供基于构造函数和基于setter的依赖注入方式去管理beans。它也提供基于setter的依赖,因为一些依赖已经通过构造函数注入成功了
您可以以BeanDefinition的形式来配置依赖性,您可以将其与PropertyEditor实例一起使用,将属性从一种格式转换为另一种格式。然而,大多数Spring用户并不直接使用这些类(例如以编程的方式),而是使用XML bean定义、带注释的组件(例如在基于java的@configuration类中,用@component、@controller等注释的类或@bean方法。然后,这些数据源被内部转换成BeanDefinition的实例,并用于加载整个Spring IoC容器实例。

Constructor-based or setter-based DI?
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.

使用基于构造函数的依赖注入还是基于setter的依赖注入?
因为您可以混合基于构造函数的和基于setter为主的DI,所以使用构造函数来强制依赖关系和setter方法或配置方法对于可选依赖关系是一个很好的经验法则。注意,在setter方法上使用@required注释可以用来使属性成为必需的依赖项。

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Spring团队通常提倡构造器注入,因为它使人能够将应用程序组件作为不可变对象实现,并确保所需的相依性不是空的。而且,在完全初始化状态下,构造注入的组件总是返回给客户端用于调用代码。作为附带说明,大量的构造函数参数是一种糟糕的代码气味,这意味着该类可能有太多的责任,应该重构,以便更好地处理适当的关注点分离。

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Setter注入应该主要只用于可选的依赖项,可以在类中分配合理的默认值。否则,在代码使用依赖项的任何地方都必须执行非null检查。setter注入的一个好处是,setter方法使该类的对象可以稍后重新配置或重新注入。因此,通过JMX mbean的管理是setter注入的一个引人注目的用例。

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

使用对特定类最有意义的DI样式。有时,在处理没有源代码的第三方类时,你可以根据实际情况进行选择。例如,如果一个第三方类没有公开任何setter方法,那么构造函数注入可能是惟一可用的DI形式。

Dependency resolution process
The container performs bean dependency resolution as follows:
依赖的处理过程
容器执行bean依赖的处理过程,如下:

The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified via XML, Java code, or annotations.

ApplicationContext是用描述所有bean的配置元数据创建和初始化的。配置元数据可以通过XML、Java代码或注释指定。

For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method if you are using that instead of a normal constructor. These dependencies are provided to the bean, when the bean is actually created.

对于每一个bean,如果您使用的不是普通的构造函数,那么它的依赖关系是通过属性、构造器参数或静态工厂方法的参数表示的。当bean真正被创建时,这些依赖项被提供给bean。

Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container.

每个属性或构造函数参数都是设定的值的实际定义,或者是容器中另一个bean的引用。

Each property or constructor argument which is a value is converted from its specified format to the actual type of that property or constructor argument. By default Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, etc.

每一个属性或构造器参数都是从它指定的格式转换成该属性或构造函数参数的实际类型。默认情况下,Spring可以将字符串格式提供的值转换为所有内置类型,如int、long、String、boolean等等。

The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean scopes. Otherwise, the bean is created only when it is requested.
Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies’ dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late, i.e. on first creation of the affected bean.

当容器被创建时,Spring容器验证每个bean的配置。然而,bean属性本身并没有设置,直到bean真正被创建为止。当容器被创建时,才会将这些预先创建好实例化(默认)的bean设置到这个单例的Bean的(先检查配置预创建Bean,等待容器创建时一起set好并加入到容器中)。作用域是在Bean范围内定义的。否则,bean只有在被请求时才会被创建。
bean的创建可能会导致创建bean的图形,因为bean的依赖关系及其依赖项(等等)被创建和分配。注意,这些依赖项之间的分辨率不匹配可能会晚些,也就是受影响的bean的第一次创建。(这句不知道怎么翻译,应该是说第一次创建bean会自动设置好里面的各种依赖,导致bean发生了变化,这些强制转换可能会出现类型不匹配这些报错的的意思吧-,-)

Circular dependencies
If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.

循环依赖
如果您主要使用构造函数(注解配置也会)注入,就有可能创建一个不可解析的循环依赖场景。

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

例如:Class A需要通过构造函数注入的Class B的实例,而Class B需要通过构造函数注入Class A的实例。如果您为类A和B配置bean,那么Spring IoC容器在运行时检测到这个循环引用,并抛出BeanCurrentlyInCreationException。

One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

一种可能的解决方案是编辑由setter而不是构造函数来配置的某些类的源代码。或者,避免构造函数注入和只使用setter注入。换句话说,虽然不推荐使用setter注入,但您可以使用setter注入来解决循环依赖的问题。

Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken/egg scenario).

与典型的情况不同(没有循环依赖),bean A和bean B之间的循环依赖会迫使其中一个bean在完全初始化之前被注入到另一个bean中(一个典型的鸡/蛋场景)。

You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container which has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies. For example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans will lazy-initialize, rather than be pre-instantiated.

你通常可以相信Spring会做正确的事。它检测到配置问题,例如在容器加载时引用不存在的bean和循环依赖项。Spring会尽可能晚地设置属性并解决依赖问题,当bean真正创建时。这意味着,如果在创建该对象或其依赖项时出现问题时,加载正确的Spring容器稍后会产生异常。例如,由于缺少或无效的属性,bean抛出异常。这可能延迟了一些配置问题的可见性,这就是为什么在默认情况下,ApplicationContext实现预先实例化单例bean( pre-instantiate singleton beans)。在实际需要之前,需要花费一些前期时间和内存来创建这些bean,在创建ApplicationContext时,您会发现配置问题,而不是以后。您仍然可以覆盖这个默认行为,这样单件bean就会延迟初始化,而不是预先实例化。(所以ApplicationContext默认是加载配置文件就检查配置文件然后就创建好bean,而不是调用容器getBean的时候才创建bean)

If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked.

如果没有循环依赖关系,当一个或多个协作bean被注入到从属bean中时,每个协作bean在被注入到从属bean之前都是完全配置的(在配置文件配置好即可)。这意味着,如果bean A对bean B有依赖性,那么Spring IoC容器在调用bean A的setter方法之前完全配置bean B,换句话说,bean是实例化的(如果不是预先实例化的单例),它的依赖项是被设置好或者相关的生命周期方法 configured init method 或 InitializingBean callback method的调用。

Examples of dependency injection
The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions:

依赖注入的例子
下面的例子使用基于setter的依赖注入的基于xml的配置元数据。Spring XML配置文件的一小部分指定了一些bean定义:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }
}

In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:

在前面的例子中,声明setter被声明与XML文件中指定的属性相匹配。下面的例子使用基于构造函数的依赖注入的例子:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- constructor injection using the nested ref element -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>

    <!-- constructor injection using the neater ref attribute -->
    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}

The constructor arguments specified in the bean definition will be used as arguments to the constructor of the ExampleBean.

bean定义中指定的构造器参数将用作ExampleBean的构造函数的参数。

Now consider a variant of this example, where instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:

现在考虑一下这个例子的一个变体,在这里,Spring被告知要调用静态工厂方法来返回的一个实例,而不是使用构造函数。

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    // a private constructor
    private ExampleBean(...) {
        ...
    }

    // a static factory method; the arguments to this method can be
    // considered the dependencies of the bean that is returned,
    // regardless of how those arguments are actually used.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }
}

Arguments to the static factory method are supplied via elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method, although in this example it is. An instance (non-static) factory method would be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so details will not be discussed here.

静态工厂方法的参数是通过构造函数提供的,与实际使用的构造函数完全相同。工厂方法返回的类的类型不必与包含静态工厂方法的类相同,尽管在本例中是这样的。一个实例(非静态)工厂方法将以一种基本相同的方式使用(除了使用工厂bean属性而不是class属性),因此这里不会讨论细节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值