Spring Core technology (ii) dependence of--spring and its injection

Source: Internet
Author: User

This article continues with the previous article, describing dependency processing in the spring Ioc.

Depend on

In general, enterprise applications will not have only one object (or spring Bean). Even the simplest applications need multiple objects to work together to make the end user see a complete Application. The next section will explain how developers can start by simply defining separate beans, to let these beans work together in one Application.

Dependency Injection

Dependency Injection is a process that allows an object to define their dependencies only by constructing parameters, parameters of factory methods, or configured Properties. These dependencies are also objects that the object needs to work Together. The container injects these dependencies when the bean is Created. The process completely reverses the instantiation or reference dependency of the Bean itself, so this process is also called inversion of control .

When the criteria for dependency injection are used, it is easier to manage dependencies between decoupled objects and make the code simpler. Objects no longer care about dependencies, and do not need to know the location of the dependent Classes. In this case, the Developer's class is easier to test, especially if the developer relies on interfaces or abstract classes, and developers can easily mock objects in unit Tests.

Dependency injection is mainly used in two ways, one is based on the injection of the constructor, and the other is based on the setter method of dependency Injection.

constructor-based Dependency Injection

constructor-based Dependency Injection is the constructor of the class that is called by the IOC container, and the parameters of the constructor represent the objects that the bean depends on. is basically the same as calling a static factory method with Parameters. The following example shows a class that implements dependency injection through a constructor Function. It is important to note that this class has no special place, just a simple, generic class that does not depend on any particular interface, base class, or annotation of any container.

publicclass SimpleMovieLister {    // the SimpleMovieLister has a dependency on a MovieFinder    private MovieFinder movieFinder;    // a constructor so that the Spring container can inject a MovieFinder    publicSimpleMovieLister(MovieFinder movieFinder) {        this.movieFinder = movieFinder;    }    // business logic that actually uses the injected MovieFinder is omitted...}
Parameter resolution of constructors

Parameter resolution of a constructor is matched by the type of the Parameter. If there is no ambiguity in the Bean's constructor arguments, then the order of the constructor arguments is the instantiation of these parameters and the order in which they are loaded. Refer to the following code:

package x.y;public class Foo {    public Foo(Bar bar, Baz baz) {        ...    }}

Assuming Bar and Baz not related at the inheritance level, there is no ambiguity, the following configuration can work properly, the developer does not need to go to the <constructor-arg> element to specify the parameters of the constructor parameter index or type Information.

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

When referencing another bean, the match works fine if the type is OK (as in the example above). when using a simple type, for example, the <value>true</value> Spring IOC container cannot determine the type of value, so it cannot be matched. Consider the following code:

package examples;publicclass ExampleBean {    // Number of years to calculate the Ultimate Answer    privateint years;    // The Answer to Life, the Universe, and Everything    private String ultimateAnswer;    publicExampleBean(int years, String ultimateAnswer) {        this.years = years;        this.ultimateAnswer = ultimateAnswer;    }}

In this case, the container can type implement a simple type match by using the properties of the constructor parameter. Like what:

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

Or use index properties to specify the location of the construction parameters, such as:

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

This index is also intended to solve the problem that there are multiple parameters of the same type in the constructor that cannot be precisely matched. It is important to note that the index is based on the 0 start.
Developers can also remove ambiguity by the name of the Parameter.

<bean  id  = "examplebean"  class  =" examples. Examplebean ";  <constructor-arg  name  = "years"  value  = "7500000" />  < constructor-arg  name  = "ultimateanswer"  value  = "a" />  </bean ;   

It is important to note that the code for this work must have debug markup compilation enabled so that spring can find the parameter names from Constructors. Developers can also use @ConstructorProperties annotations to explicitly declare the name of a constructor, such as the following code:

package examples;publicclass ExampleBean {    // Fields omitted    @ConstructorProperties({"years""ultimateAnswer"})    publicExampleBean(int years, String ultimateAnswer) {        this.years = years;        this.ultimateAnswer = ultimateAnswer;    }}

Dependency Injection based on setter mode
A dependency injection based on a setter function is a container that invokes a Bean's parameterless constructor, or a factory method without parameters, and then calls the setter method to implement the dependency Injection.

The following example shows a dependency injection using the setter method, the following class object is simply a Pojo object, independent of any spring special interface, base class, or Annotation.

public   Class  Simplemovielister {//the Simplemovielister have a dependency on the Moviefinde    R  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 This actually uses the injected Moviefinder is omitted ... } 

ApplicationContextManaged beans are supported for constructor-based dependency injection or setter-based dependency Injection. It also supports the use of setter methods to inject dependency again after the dependency is injected through the Constructor. Developers BeanDefinition can use PropertyEditor instances to freely choose the way they are injected. however, most developers do not use these classes directly, but rather with bean definitions that prefer xml, or annotations-based components (such as use @Component , @Controller etc.) or methods that are used on the configured @Configuration classes @Bean .

is it based on a constructor or setter method?
Because developers can mix both, it is usually better to inject the necessary dependencies through the constructor to inject some optional dependencies through the Setter. The annotations above the setter method @Required can be used to construct the necessary dependencies.
The spring team recommends a constructor-based injection, because this approach encourages developers to develop components into immutable objects and ensures that the injection dependency is not null . also, the constructor-based injected component is fully constructed when it is called by the Client. of course, on the other hand, too many of the constructor parameters are very bad code, which means that the class seems to have too many functions, and it is best to refactor different functions Apart.
setter-based injection is only for optional dependencies, but it is also best to configure some reasonable default Values. otherwise, A non-null check is required on the dependencies of the Code. One of the conveniences of setter-based injection is that this approach can be re-configured and Re-injected.
Two styles of dependency injection are suitable for most situations, but sometimes when using a third-party library, the developer may not have the source code, and the Third-party codes do not have setter methods, then only the constructor-based dependency injection is Used.

Dependency parsing process

The container parses the bean as Follows:

    • Created and instantiated according to the metadata of the description ApplicationContext . Configuration metadata can be through xml, Java code, or Annotations.
    • The dependency of each bean is represented by a constructor parameter or a property or parameter of a static factory Method. These dependencies are injected and loaded when the bean is Created.
    • Each property or constructor parameter is either an actual defined value or a reference to another bean in the Container.
    • Each property or construct parameter can be converted according to its specified type. Spring can also turn a string into the default Java intrinsic type, such as,, int long String , boolean etc.

The spring container is validated against each bean at the time the container is Created. however, the Bean's properties are not configured when the bean is not actually created. A singleton type of Bean is configured as a pre-instance state when the container is Created. The Bean is Scope introduced in a FOLLOW-UP. Other beans are created only at the time of the Request. Obviously creating a bean object will have a dependency graph. This diagram represents a dependency between beans, which the container determines the order in which the beans are created and configured.

Cyclic Dependency
If the developer primarily uses a constructor-based dependency injection, there is a good chance that a loop-dependent scenario will Occur.
For example, Class A relies on an instance of Class B in a constructor, whereas a constructor of Class B relies on an instance of Class A. If you do this by configuring Class A and Class B to inject each other, the Spring IOC container will find this runtime's cyclic dependency and throw it BeanCurrentlyInCreationException .
Developers can use setter methods to configure dependency injection, which solves this Problem. or, instead of using constructor-based dependency injection, use only dependency injection based on the setter Method. In other words, Although not recommended, developers can configure cyclic dependencies as dependency injection based on setter METHODS.

Developers can trust spring to handle beans correctly. Spring can discover configuration problems during loading, such as referencing to nonexistent beans or cyclic dependencies. Spring will load attributes or parse dependencies as late as the Bean is Created. This also means that the spring container is loaded correctly and throws an exception when the bean injection dependency error Occurs. For example, The bean throws a missing attribute or the property is Illegal. The parsing of this delay is also why ApplicationContext the implementation causes the singleton bean to be in the Pre-instantiation State. This way, by ApplicationContext creating, You can consume some memory costs before actually using the bean to discover the configuration Problem. Developers can also override the default behavior to delay loading a singleton bean instead of being in a pre-instantiated State.
If there is no circular dependency, the dependency that the bean refers to will take precedence over the fully constructed Dependency. For example, if Bean a relies on bean b, the spring IOC container configures Bean B First and then invokes the setter method of bean A to construct Bean A. In other words, The bean is instantiated first, then injected into the dependency, and then the invocation of the associated life cycle Method.

example of dependency injection
The following example uses metadata based on XML configuration and then uses setter mode for dependency Injection. The code is as Follows:

<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 classExamplebean {PrivateAnotherbean beanone;PrivateYetanotherbean beantwo;Private intI public void Setbeanone(anotherbean beanone) { this. Beanone = beanone; } public void Setbeantwo(yetanotherbean Beantwo) { this. Beantwo = beantwo; } public void Setintegerproperty(intI) { this. i = i; }}

In the above example, the setter method declaration is consistent with the XML file, and the following example is a constructor-based dependency injection

<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 "/> 
publicclass ExampleBean {    private AnotherBean beanOne;    private YetAnotherBean beanTwo;    privateint i;    publicExampleBean(        int i) {        this.beanOne = anotherBean;        this.beanTwo = yetAnotherBean;        this.i = i;    }}

The constructor parameter in the bean definition is the dependency that is used to construct ExampleBean .

The following example returns a Bean instance through a static factory Method.

<beanID="examplebean" class="examples. Examplebean "Factory-method="createinstance"> <constructor-argref="anotherexamplebean"/> <constructor-argref="yetanotherbean"/> <constructor-arg value="1"/></bean><beanID="anotherexamplebean" class="examples. Anotherbean "/><beanID="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;    }}

The parameters of the factory method are also specified by the <constructor-arg/> label, and the dependency injection based on the constructor is Consistent. As mentioned before, the returned type does not need to be consistent with the exampleBean class attributes in, and the class class that contains the factory method is Specified. of course, The above example is Consistent. The factory-bean instance factory method used to construct the bean is not much described here.

Spring Core technology (ii) dependency and injection of--spring

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.