依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念。
当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的实例(例如,使用 new 关键字获得被调用者实例),而使用 Spring 框架后,被调用者的实例不再由调用者创建,而是由 Spring 容器创建,这称为控制反转。
Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring 容器获得被调用者实例,这称为依赖注入。
依赖注入主要有两种实现方式,分别是属性 setter 注入和构造方法注入。具体介绍如下。
1)属性 setter 注入
指 IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean 的 setter 方法,即可实现基于 setter 的 DI。
2)构造方法注入
指 IoC 容器使用构造方法注入被依赖的实例。基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖。
下面通过属性 setter 注入的案例演示 Spring 容器是如何实现依赖注入的。具体步骤如下。
1. 创建 PersonService 接口
在 springDemo01 项目的 com.mengma.ioc 包下创建一个名为 PersonService 的接口,该接口中包含一个 addPerson() 方法,如下所示。
package com.mengma.ioc;
public interface PersonService {
public void addPerson();
}
2. 创建接口实现类 PersonServiceImpl
在 com.mengma.ioc 包下创建一个名为 PersonServiceImpl 的类,该类实现了 PersonService 接口,如下所示。
package com.mengma.ioc;
public class PersonServiceImpl implements PersonService {
// 定义接口声明
private PersonDao personDao;
// 提供set()方法,用于依赖注入
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
// 实现PersonService接口的方法
@Override
public void addPerson() {
personDao.add(); // 调用PersonDao中的add()方法
System.out.println("addPerson()执行了...");
}
}
首先声明了 personDao 对象,并为其添加 setter 方法,用于依赖注入,然后实现了 PersonDao 接口的 addPerson() 方法,并在方法中调用 save() 方法和输出一条语句。
3. 在 applicationContext.xml 中添加配置信息
在 applicationContext.xml 配置文件中添加一个 <bean> 元素,用于实例化 PersonServiceImpl 类,并将 personDao 的实例注入到 personService 中,其实现代码如下所示:
<bean id="personService" class="com.mengma.ioc.PersonServiceImpl">
<!-- 将personDao实例注入personService实例中 -->
<property name="personDao" ref="personDao"/>
</bean>
4. 编写测试方法
在 FirstTest 类中创建一个名为 test2() 的方法,编辑后如下所示:
@Test
public void test2() {
// 定义Spring配置文件的路径
String xmlPath = "applicationContext.xml";
// 初始化Spring容器,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
xmlPath);
// 通过容器获取personService实例
PersonService personService = (PersonService) applicationContext
.getBean("personService");
// 调用personService的addPerson()方法
personService.addPerson();
}
5. 运行项目并查看结果
使用 JUnit 测试运行 test2() 方法,运行成功后,控制台的输出结果如图 。

可以看出,使用 Spring 容器获取 userService 的实例后,调用了该实例的 addPerson() 方法,在该方法中又调用了 PersonDao 实现类中的 add() 方法,并输出了结果。这就是 Spring 容器属性 setter 注入的方式,也是实际开发中较为常用的一种方式。

吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring DI(依赖注入)的实现方式属性注入和构造注入的更多相关文章

  1. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:继承的应用

    class Array{ // 表示数组 private int temp[] ; // 整型数组 private int foot ; // 定义添加位置 public Array(int len) ...

  2. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:匿名内部类

    interface A{ public void printInfo() ; // } class B implements A{ // 实现接口 public void printInfo(){ S ...

  3. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:包装类

    public class WrapperDemo01{ public static void main(String args[]){ int x = 30 ; // 基本数据类型 Integer i ...

  4. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:Object类

    class Demo{ // 定义Demo类,实际上就是继承了Object类 }; public class ObjectDemo01{ public static void main(String ...

  5. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:宠物商店实例分析

    interface Pet{ // 定义宠物接口 public String getName() ; public String getColor() ; public int getAge() ; ...

  6. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:抽象类与接口的应用

    abstract class A{ // 定义抽象类A public abstract void print() ; // 定义抽象方法print() }; class B extends A { / ...

  7. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:instanceof关键字

    class A{ // 定义类A public void fun1(){ // 定义fun1()方法 System.out.println("A --> public void fun ...

  8. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:对象的多态性

    class A{ // 定义类A public void fun1(){ // 定义fun1()方法 System.out.println("A --> public void fun ...

  9. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:接口的基本实现

    interface A{ // 定义接口A public static final String AUTHOR = "李兴华" ; // 全局常量 public abstract ...

  10. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:final关键字

    final class A{ // 使用final定义类,不能有子类 }; class B extends A{ // 错误,不能被继承 }; class A{ public final void p ...

随机推荐

  1. ElasticSearch入门了解

    什么是Elasticsearch: Elasticsearch,分布式,高性能,高可用,可伸缩的搜索和分析系统 1.什么是搜索? 搜索,就是在任何场景下,找寻你想要的信息,这个时候,会输入一段你要搜索 ...

  2. oracle的存储过程和函数有什么区别?

    Oracle中的函数与存储过程的区别:      A:函数必须有返回值,而过程没有. B:函数可以单独执行.而过程必须通过execute执行. C:函数可以嵌入到SQL语句中执行.而过程不行. 其实我 ...

  3. [笔记]ul>li>a做分布时, 让其居中显示效果

    结构: <div id="page"> <ul> <li><a href="#">首页</a>< ...

  4. 8 Jvm堆分析

    备注:直接内存分配,无法触发GC动作 备注:with outgoing reference (当前选中对象引用的对象),with incoming references(引用当前对象的对象)

  5. leeetcode1171 Remove Zero Sum Consecutive Nodes from Linked List

    """ Given the head of a linked list, we repeatedly delete consecutive sequences of no ...

  6. pom.xml报unknown error

    1. 从https://start.spring.io/的spring initializr生成demo,使用默认的2.1.6.release(2019年7月10日) 2. 在eclipse加载后,p ...

  7. NO5 grep-head-tail命令

    ·*****grep:#过滤需要的内容(linux三剑客).                   -v:排除内容.eg:grep -v oldboy test.txt ·head: #头,头部.读取文 ...

  8. 获取指定进程号,并kill掉

    直接上案例: 例子:获取nginx进程 方法:$ps -aux |grep nginx |grep -v grep |awk '{print $2}'  或者 $ps -ef |grep nginx ...

  9. JavaScript.StringObjec.replace

    //StringObject.replace(/regexp/,newContent); //1当newContent为新字符串,就直接用newContent对匹配的内容进行替换. //2当newCo ...

  10. Bug 佛祖镇楼

    原文链接:https://www.cnblogs.com/xdp-gacl/p/4198935.html // _ooOoo_ // o8888888o // 88" . "88 ...