What is dependency injection?

Transfer from https://blog.csdn.net/coding_1994/article/details/80634810, the authors write very clear.

 

Spring can effectively organize J2EE application layers of the object. Whether Action objects control layer, business layer objects or Service, or DAO object persistence layer, can be organically coordinated in the Spring of management and operation. Spring the layers of objects grouped together in a loosely coupled manner, Action objects without concern for the Service object specific implementation, the Service object without concern for the persistence layer to achieve specific object, call the object layers completely oriented interface. When the system needs reconstruction, to rewrite the code amount will be greatly reduced.

Everything mentioned above had a core mechanism suitable for Spring, dependency injection. Dependency injection to make the configuration files together, rather than hard-coding coupled together between bean and bean. Appreciated dependency injection

dependency injection (Dependency Injection) and reverse control (Inversion of Control) is the same concept. Specific meaning is: When a role (probably a Java instance, the caller) need help another role (another Java instance, the callee) when, in the traditional program design process, usually created by the caller examples of the caller. However, in Spring, work created by the caller by the caller will not be complete, so called inversion of control; Create instance callee work is usually done by Spring container, and then injected into the caller, it is also known dependent injection.

Whether dependency injection, or inversion of control, were indicative of Spring dynamic, flexible way to manage a variety of objects. DETAILED between the object and each object implementation transparent. Before understanding of dependency injection, see below how to solve this problem in a variety of social state: a man (Java instance, the caller) needs an ax (Java instance, the caller).

(1) primitive society, almost no social division of labor. People (the caller) need only their own ax to grind an ax (the caller). Corresponding to the case: Java program in the caller's own creation is called.

(2) into the industrial society, the factory appears. Ax no longer done by ordinary people, and are produced in the factory, this time people (the caller) needs to find an ax factory, buy ax, ax without concern for the manufacturing process. Simple factory design pattern corresponding Java program.

(3) into the "on demand" society, people do not need to find the required ax factory, sit at home and issued a simple directive: the need for an ax. Ax naturally in front of him. Spring corresponding to the dependency injection.

In the first case, the caller Java instances created Java instance is invoked, the Java class is called an inevitable requirement appears in the caller's code. Unable to achieve loose coupling between the two.

In the second case, the caller need not be concerned about the caller specific implementation process, just need to find instances meet certain criteria (Interface), you can use. Code oriented programming interface calls at this time, allowing the caller and callee decoupling, which is why a lot of use of the factory model. But the caller needs to position itself factory, with a particular caller factory coupled together.

In the third case, the caller without locating factories themselves, the program needs to be run to the caller, the caller is automatically provided examples. In fact, the caller and the callee are in Spring under the management of the dependencies between them provided by Spring.

The so-called dependency injection, refers to the program is running, if you need assistance call another object, without having to create the caller is in the code, but instead relies on external injection. Spring's dependency injection almost no requirement for the caller and the callee, fully supports the management of dependencies between POJO (Plain Ordinary Java Object) is. There are usually two dependency injection:

· setter injection.

· Construction injection.
 
Set value of the injected

  setter injection means passed by the caller by the method of Example setter. This injection method is simple, intuitive, and therefore widely used in the Spring dependency injection. Look at the following code, Person interface
// Define Person Interface
public interface Person{
    // Person interfaces defined in a method of using the ax
    public void useAxe();
}

  

 

Then Axe interface
// define Axe Interface
public interface Axe{
    // Axe the interface has had a cut method
    public void chop();
}

  

 

Person of the implementation class
public class Chinese implements Person{
    // Axe oriented programming interface, rather than a specific category
    private Axe axe;
    // default constructor
    public Chinese(){
    }
    // set the desired value setter injection method
    public void setAxe(Axe axe){
        this.axe = axe;
    }
    useAxe method // implement Person interface
    public void useAxe(){
        System.out.println(axe.chop());
    }
}

  



Axe first implementation class
// Axe first implementation class StoneAxe

public class StoneAxe the implements Ax
{
// default constructor
public StoneAxe ()
{}
// CHOP implemented method of Ax interface
public String CHOP ()
{
return "firewood very slow axes";
}
}

Spring uses the following configuration file and the Person instance Axe Examples of tissue together. The configuration file as follows:
<! - The following is a standard XML file header ->
<xml Version = "1.0" encoding = "GB2312"??>
<- dtd XML configuration files defined in the following line of Spring -!>
"HTTP: / /www.springframework.org/dtd/spring-beans.dtd ">
<! - more than three lines of all the Spring configuration file is the same ->
<! - the root element of the Spring configuration file ->
< BEANS>
<-! defining a first bean, which is the id chinese, class specify a class instance of the bean ->
<bEAN class = "Lee" id = chinese .Chinese>
<-! Property element is used to specify the injected properties required of the container, the container needs to Ax injection property value set here is injected, therefore the class must have Chinese setAxe method ->
<Property name = "Ax">
<-! Another reference herein to implantation bean bean chinese ->
<= the REF local "" stoneAxe "/">
</ Property>
</ BEAN>
<! - defines the bean stoneAxe ->
<BEAN class = "Lee" .StoneAxe ID = stoneAxe />
</ BEANS>

From the configuration file, you can see dexterity Spring-managed bean. dependencies between the bean and bean configuration file on the organization, not in the code itself. By specifying the configuration file, Spring bean accurately for each injection property. Therefore, the configuration file of the bean class element, not only is the interface, and implementation class must be real.

Spring will automatically take over the property of each bean definition in the element definition. Spring will be performed after the free parameters of the constructor, creates a default bean example, call the corresponding property value setter method injection procedure. attribute property values will no longer be defined by that the bean automatically create, manage, and instead passively received Spring injection.

Id attribute uniquely identifies each bean is the bean, the program through the id attribute access bean, bean and bean dependence is also done by the id attribute.

Let's look at part of the main program:
BeanTest class public
{
// main method, a program entry
public static void main (String [] args) throws Exception
{
// because it is independent of the application, context explicitly instantiate the Spring.
CTX = new new a FileSystemXmlApplicationContext the ApplicationContext ( "bean.xml");
// acquired by the Person bean bean instance id, oriented programming interface, so
// This interface type casts
Person p = (Person) ctx.getBean ( "chinese");
// direct execution of userAxe Person () method.
p.useAxe ();
}
}

程序的执行结果如下:

石斧砍柴好慢

主程序调用Person的useAxe()方法时,该方法的方法体内需要使用Axe的实例,但程序里没有任何地方将特定的Person实例和Axe实 例耦合在一起。或者说,程序里没有为Person实例传入Axe的实例,Axe实例由Spring在运行期间动态注入。

Person实例不仅不需要了解Axe实例的具体实现,甚至无须了解Axe的创建过程。程序在运行到需要Axe实例的时候,Spring创建了Axe 实例,然后注入给需要Axe实例的调用者。Person实例运行到需要Axe实例的地方,自然就产生了Axe实例,用来供Person实例使用。

调用者不仅无须关心被调用者的实现过程,连工厂定位都可以省略(真是按需分配啊!)。下面也给出使用Ant编译和运行该应用的简单脚本:
<?xml version="1.0"?>
<!-- 定义编译该项目的基本信息-->
<PROJECT name="spring" default="." basedir=".">
<!-- 定义编译和运行该项目时所需的库文件 -->
<PATH id=classpath>
<!-- 该路径下存放spring.jar和其他第三方类库 -->
<FILESET dir=../../lib>
<INCLUDE name="*.jar" />
</FILESET>
<!-- 同时还需要引用已经编译过的class文件-->
<PATHELEMENT path="." />
</PATH>
<!-- 编译全部的java文件-->
<TARGET description="Compile all source code" name="compile">
<!-- 指定编译后的class文件的存放位置 -->
<JAVAC debug="true" destdir=".">
deprecation="false" optimize="false" failοnerrοr="true">
<!-- 指定需要编译的源文件的存放位置 -->
<SRC path="." />
<!-- 指定编译这些java文件需要的类库位置-->
<CLASSPATH refid="classpath" />
</JAVAC>
</TARGET>
<!-- 运行特定的主程序 -->
<TARGET description="run the main class" name="run" depends="compile">
<!-- 指定运行的主程序:lee.BeanTest。-->
<JAVA failοnerrοr="true" fork="yes" classname="lee.BeanTest">
<!-- 指定运行这些java文件需要的类库位置-->
<CLASSPATH refid="classpath" />
</JAVA>
</TARGET>
</PROJECT>

如果需要改写Axe的实现类。或者说,提供另一个实现类给Person实例使用。Person接口、Chinese类都无须改变。只需提供另一个Axe的实现,然后对配置文件进行简单的修改即可。

Axe的另一个实现如下:
//Axe的另一个实现类 SteelAxe
public class SteelAxe implements Axe
{
//默认构造器
public SteelAxe()
{}
//实现Axe接口的chop方法
public String chop()
{
return "钢斧砍柴真快";
}
}

然后,修改原来的Spring配置文件,在其中增加如下一行:
<!-- 定义一个steelAxe bean-->
<BEAN class="lee".SteelAxe id=steelAxe />

该行重新定义了一个Axe的实现:SteelAxe。然后修改chinese bean的配置,将原来传入stoneAxe的地方改为传入steelAxe。也就是将
<REF local="”stoneAxe”/">

改成
<REF local="”steelAxe”/">

此时再次执行程序,将得到如下结果:

钢斧砍柴真快

Person与Axe之间没有任何代码耦合关系,bean与bean之间的依赖关系由Spring管理。采用setter方法为目标bean注入属性的方式,称为设值注入。

业务对象的更换变得相当简单,对象与对象之间的依赖关系从代码里分离出来,通过配置文件动态管理。
构造注入

  所谓构造注入,指通过构造函数来完成依赖关系的设定,而不是通过setter方法。对前面代码Chinese类做简单的修改,修改后的代码如下:
//Chinese实现Person接口
public class Chinese implements Person
{
//面向Axe接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese()
{}
//构造注入所需的带参数的构造器
public Chinse(Axe axe)
{
this.axe = axe;
}
//实现Person接口的useAxe方法
public void useAxe()
{
System.out.println(axe.chop());
}
}

此时无须Chinese类里的setAxe方法,构造Person实例时,Spring为Person实例注入所依赖的Axe实例。构造注入的配置文件也需做简单的修改,修改后的配置文件如下:
<!-- 下面是标准的XML文件头 -->
<xml version="1.0" encoding="gb2312"?>
<!-- 下面一行定义Spring的XML配置文件的dtd -->
"http://www.springframework.org/dtd/spring-beans.dtd">
<!-- 以上三行对所有的Spring配置文件都是相同的 -->
<!-- Spring配置文件的根元素 -->
<BEANS>
<!—定义第一个bean,该bean的id是chinese, class指定该bean实例的实现类 -->
<BEAN class="lee".Chinese id=chinese>
</BEAN>
<!-- 定义stoneAxe bean -->
<BEAN class="lee".SteelAxe id=steelAxe />
</BEANS>

执行效果与使用steelAxe设值注入时的执行效果完全一样。区别在于:创建Person实例中Axe属性的时机不同——设值注入是现创建一个默认的bean实例,然后调用对应的构造方法注入依赖关系。而构造注入则在创建bean实例时,已经完成了依赖关系的

Guess you like

Origin www.cnblogs.com/baxianhua/p/11735187.html