在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。

Spring依赖注入(DI)的三种方式,分别为:

1.  Setter方法注入

2.  构造方法注入

3.  接口注入

下面介绍一下这三种依赖注入在Spring中是怎么样实现的。

Setter方法注入

首先我们需要以下几个类:

接口 Logic.java

接口实现类 LogicImpl.java

一个处理类 LoginAction.java

还有一个测试类 TestMain.java

Logic.java如下:

<span style="font-size:18px;"><span style="font-size:18px;">package DI;
//定义接口
public interface Logic {
public String getName();
}
</span></span>

LogicImpl.java如下:

<span style="font-size:18px;"><span style="font-size:18px;">package DI;

public class LogicImpl implements Logic {
//实现类 public String getName() { return "lishehe";
} }
</span></span>

LoginAction.java 会根据使用不同的注入方法而稍有不同

Setter方法注入:

<span style="font-size:18px;"><span style="font-size:18px;">package DI;

public class LoginAction {
private Logic logic; public void execute() { String name = logic.getName(); System.out.print("My Name Is " + name); } /** * @return the logic */ public Logic getLogic() { return logic; } /** * @param logic * the logic to set */ public void setLogic(Logic logic) { this.logic = logic; }
}
</span></span>

客户端测试类

TestMain.java

<span style="font-size:18px;">package DI;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext; public class TestMain { /** * @param args */ public static void main(String[] args) { // 得到ApplicationContext对象 ApplicationContext ctx = new FileSystemXmlApplicationContext( "applicationContext.xml"); // 得到Bean LoginAction loginAction = (LoginAction) ctx.getBean("loginAction"); loginAction.execute(); }
}
</span>

定义了一个Logic 类型的变量 logic, 在LoginAction并没有对logic 进行实例化,而只有他对应的setter/getter方法,因为我们这里使用的是Spring的依赖注入的方式

applicationContext.xml配置文件如下:

<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>

<!--
- Application context definition for JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="logic" class="DI.LogicImpl"/> <bean id="loginAction" class="DI.LoginAction"> <property name="logic" ref="logic"></property> </bean> </beans>
</span>

运行效果:

构造器注入

顾名思义,构造方法注入,就是我们依靠LoginAction的构造方法来达到DI的目的,如下所示:

<span style="font-size:18px;">package DI;

public class LoginAction {

	 private Logic logic;

	    public LoginAction(Logic logic) {

	       this.logic = logic;

	    }

	    public void execute() {

	       String name = logic.getName();

	       System.out.print("My Name Is " + name);

	    }

}
</span>

里我们添加了一个LoginAction的构造方法

applicationContext.xml配置文件如下:

<span style="font-size:18px;">	<bean id="logic" class="DI.LogicImpl"/>

<bean id="loginAction" class="DI.LoginAction">

 <constructor-arg index="0" ref="logic"></constructor-arg>

</bean></span>

我们使用constructor-arg来进行配置,
index属性是用来表示构造方法中参数的顺序的,如果有多个参数,则按照顺序,从 0,1...来配置

我们现在可以运行testMain.java了,结果跟使用Setter方法注入完全一样.

效果图

其中需要注意一点有:构造函数有多个参数的话,如:参数1,参数2,而参数2依赖于参数1,这中情况则要注意构造函数的顺序,必须将参数1放在参数2之前。

接口注入

下面继续说说我们不常用到的接口注入,还是以LogicAction为例,我们对他进行了修改,如下所示:

LogicAction.java

<span style="font-size:18px;">package DI;

public class LoginAction {

	private Logic logic;

    public void execute() {

       try {

           Object obj = Class.forName("DI.LogicImpl")

                  .newInstance();

           logic = (Logic) obj;

           String name = logic.getName();

           System.out.print("My Name Is " + name);

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

}
</span>

配置文件:

<span style="font-size:18px;"><bean id="logic" class="DI.LogicImpl"/>

<bean id="loginAction" class="DI.LoginAction"></span>

效果图

总结

对于Spring的依赖注入,最重要的就是理解他的,一旦理解了,将会觉得非常的简单。无非就是让容器来给我们实例化那些类,我们要做的就是给容器提供这个接口,这个接口就我们的set方法或者构造函数了。

SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式的更多相关文章

  1. SSH深度历险记(八) 剖析SSH核心原则+Spring依赖注入的三种方式

           于java发育.一类程序猿必须依靠类的其他方法,它是通常new依赖类的方法,然后调用类的实例,这样的发展问题new良好的班统一管理的例子.spring提出了依赖注入的思想,即依赖类不由程 ...

  2. SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)

    接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文采用强制的CGLB代理方式 Security ...

  3. SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...

  4. 30个类手写Spring核心原理之依赖注入功能(3)

    本文节选自<Spring 5核心原理> 在之前的源码分析中我们已经了解到,依赖注入(DI)的入口是getBean()方法,前面的IoC手写部分基本流程已通.先在GPApplicationC ...

  5. java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

  6. (转)编码剖析Spring依赖注入的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...

  7. 【SSH进阶之路】Spring的IOC逐层深入——依赖注入的两种实现类型(四)

    上篇博文,我们介绍了为什么使用IOC容器,和IOC的设计思想以及IOC容器的优缺点,并且给大家转载了一篇介绍IOC原理的博文,我们这篇主要给大家依赖注入的两种方式,以及他们的优缺点. 我们这篇博文还是 ...

  8. SSH深度历险(六) 深入浅出----- Spring事务配置的五种方式

    这对时间在学习SSH中Spring架构,Spring的事务配置做了详细总结,在此之间对Spring的事务配置只是停留在听说的阶段,总结一下,整体把控,通过这次的学习发觉Spring的事务配置只要把思路 ...

  9. Spring、Spring依赖注入与编码剖析Spring依赖注入的原理

    Spring依赖注入 新建PersonIDao 和PersonDao底实现Save方法: public interface PersonIDao { public void save(); } pub ...

随机推荐

  1. 【Rain in ACStar HDU-3340】

    ·你正从AC星球返回,天又下起凸包雨,只好到线段树下躲雨. ·英文题,述大意:       一个竖直平面的美丽天空,会下凸包雨.凸包雨指的是边数为3~6的多边形,并且每一个它都遵守一个神奇定律,那就是 ...

  2. Python中模块之time&datetime的功能介绍

    time&datetime的功能介绍 1. time模块 1. 时间的分类 1. 时间戳:以秒为单位的整数 2. 时间字符格式化:常见的年月日时分秒 3. 时间元祖格式:9大元素,每个元素对应 ...

  3. 一款基于Vue的扩展性组件库 VV-UI

    github: https://github.com/VV-UI/VV-UI 演示地址: https://vv-ui.github.io/VV-UI/#/meta-info 1. LoadingBar ...

  4. DDD实战进阶第一波(七):开发一般业务的大健康行业直销系统(实现产品上下文接口与测试)

    前一篇文章我们介绍了如何将创建产品的领域逻辑与产品的持久化仓储通过上架产品的用例组织起来,完成了一个功能.在实际的项目中,多种前端的形态比如PC Web. 微信小程序.原生APP等要调用后端的功能,通 ...

  5. java获取当前系统时间

    阿里巴巴推荐 Timestamp d = new Timestamp(System.currentTimeMillis()); 唯一的好处就是除了Timestamp,没有再新建什么了

  6. EM vs REM vs PX,为什么你不应该”只用px“”

    Actually this artical is from other person's opnion ,i just put it into chinese,and this means a ver ...

  7. JAVA (集合和数据结构)

    Collection和Collections的区别: 1.java.util.Collection 是一个集合接口.它提供了对集合对象进行基本操作的通用接口方法.Collection接口在Java 类 ...

  8. ubuntu远程桌面连接命令rdesktop连接windows远程桌面详解

    sudo apt-get install rdesktoprdesktop 124.42.120.174:1433 呵呵,连接成功了. -f 全屏-a 16位色默认端口是3389(linux 22 s ...

  9. range和xrange的区别详解

    两种用法介绍如下:1.range([start], stop[, step])返回等差数列.构建等差数列,起点是start,终点是stop,但不包含stop,公差是step.start和step是可选 ...

  10. 关于bedtools merge 功能中sort 命令的解释

    Bedtools 是一个很好的用来处理区间的工具,很多时候用这个底层语言编写的小工具比自己写的脚本运行快很多,但是这个工具中的某些功能对输入文件有一定的要求,比如说里面的一个merge函数,这是里面的 ...