简单解析依赖注入(控制反转)在Spring中的应用

IoC——Inversion of Control  控制反转
DI——Dependency Injection   依赖注入

大家都知道,依赖注入是Spring中非常重要的一种设计模式。可能很多初学者对这种看起来高深的东西有一种抗拒,这里就
 简单介绍一下到底什么是依赖注入,Spring到底又到底是如何运用依赖注入的。

依赖关系:在A组件中要引用B组件的对象,则称A依赖于B
依赖关系会造成各组件之间的硬编码,为解决依赖关系,一般的解决方法如下:

1、A组件先创建B组件,在调用B组件方法
2、A组件先通过B组建的工厂获取B组件,再调用B组件方法
3、A、B两个组件都由容器管理,容器先将B组件传给A组件,A组件直接调用B的方法

第一个是传统的方法,并没有解决依赖关系
第二个则造成了A与工厂类的耦合
Spring就是通过第三种方法解决的,被称为依赖注入。

依赖注入和控制反转其实就是将的同一个设计模式,只是从不同的角度进行描述的。
依赖注入是从组件之依赖关系讲的,指A不再主动的去创建B组件,而变为被动的接受容器的注入的B对象;
而控制反转是从对对象的控制方面讲的,是指程序代码直接操控的对象的调用权交给容器。

依赖注入包括两种方式,一是设值注入,一是构造注入。下面就以Spring中具体代码实现例子来解释两种依赖注入方式:

1、数据库操作的接口:
 1 public interface UserDao { 2 3 void save(String name,String pass); 4 }

2、接口两种实现方式:
程序只是简单模拟连接数据库,并没有真正进行连接:
(1)

 1 import com.csu.test.dao.UserDao;
 2
 3 public class UserDaoJdbc implements UserDao{
 4
 5     @Override
 6     public void save(String name, String pass) {
 7
 8         System.out.println("模拟通过JDBC存储用户:"+name );
 9     }
10
11 }

(2)

 1 import com.csu.test.dao.UserDao;
 2
 3 public class UserDaoHibernate implements UserDao{
 4
 5     @Override
 6     public void save(String name, String pass) {
 7
 8         System.out.println("模拟通过Hibernate存储用户:"+name );
 9     }
10
11 }

3、Service 层:

 1 import org.springframework.context.ApplicationContext;
 2 import org.springframework.context.support.ClassPathXmlApplicationContext;
 3
 4 import com.csu.test.dao.UserDao;
 5
 6 public class UserService {
 7
 8     private UserDao userDao;
 9
10
11
12     //1、通过为userDao提供sett方法,在配置文件中的property属性进行配置,即可解决A依赖B的问题
13     public void setUserDao(UserDao userDao) {
14         this.userDao = userDao;
15     }
16
17     //2、通过构造方法进行配置
18     public UserService(UserDao userDao){
19         this.userDao = userDao;
20     }
21
22
23
24     public void addUser(String name,String pass){
25         //UserDao userDao = new UserDao();
26         //UserDao userDao = new UserDaoJdbc();
27         //UserDao userDao = UserDaoFactory.getUserDao();
28
29         /**
30         //spring中可以向创建Spring容器
31         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
32         UserDao userDao = ctx.getBean("userdao",UserDao.class);
33         userDao.save(name, pass);
34         **/
35
36         userDao.save(name, pass);
37     }
38 }

4、配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<!-- 整个Spring 文件的根元素就是beans -->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 这行代码 相当于一个产品-->
    <bean id="userdaoJdbc" class="com.csu.test.dao.impl.UserDaoJdbc"/>
    <bean id="userdaoHibernate" class="com.csu.test.dao.impl.UserHibernate"/>

    <bean id = "userService" class="com.csu.test.service.UserService">
        <!-- property就是控制调用setter方法 -->
        <!--  <property name = "userDao" ref = "userdaoJdbc"/> -->

        <!-- 调用有参构造器 -->
        <constructor-arg ref = "userdaoJdbc"/>

    <!--更换实现方式-->
    <!--
        <property name = "userDao" ref = "userdaoHibernate"/>
        <constructor-arg ref = "userdaoHibernate"/>
    -->
    </bean>

</beans>

这里重点解释一下吧:
在service层中的UserService类中,是依赖于数据库操作对象UserDao的,如大家所见,UserService类中我们并没有直接new出UserDao对象的,
怎么做到的呢:两种方式
(1)、设值注入:
对应函数为:public void setUserDao(UserDao userDao)
在配置文件中,对应id为userService的Bean设置,有一个property的属性,这意味着,当我们在得到userService的Bean对象时,根据property的属性,容器会自动调用
与name相应的set函数,即上面的函数,传入的参数依旧为Bean对象,所以用ref

(2)、构造注入
对应函数为:public UserService(UserDao userDao)
与设值注入类似,<constructor-arg>标签的含义就是调用构造函数,传递参数,自动实例化UserDao。

当然两种方式不要重复设置,上面已经注释掉一种,可以自己再测试一下。

5、测试主类:

 1 import org.junit.Before;
 2 import org.junit.Test;
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5
 6 import com.csu.test.dao.UserDao;
 7 import com.csu.test.service.UserService;
 8
 9 public class TestService {
10
11     UserService u;
12
13     @Test
14     public void testAddUser(){
15         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
16         u = ctx.getBean("userService",UserService.class);
17
18         u.addUser("admin", "123");
19     }
20 }

这样,我们就实现了面向接口编程,具体的实现类配置在配置文件即可,像上面的代码,我们只需要更改配置文件,
就可以改变数据库的操作对象。

时间: 2024-10-20 19:43:34

简单解析依赖注入(控制反转)在Spring中的应用的相关文章

Helloworld之Spring依赖注入/控制反转(DI/IoC)版

Helloworld之Spring依赖注入/控制反转(DI/IoC)版 作者:雨水, 日期:2014-10-29 摘要:本文主要用于培训初学者理解Spring中的依赖注入的基本概念. 先介绍依赖注入的基本概念,然后以构造器注入为例实现了Helloworld实例. Spring依赖注入/控制反转 在我们通常的编程中,如果类A要依赖类B,通常是由A来创建一个B的实例.而Spring将创建B的实例的工作交给Spring容器来完成,然后注入A,因此称为依赖注入(DI, Dependency Inject

C#依赖注入控制反转IOC实现详解

原文:C#依赖注入控制反转IOC实现详解 IOC的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器负责将这些联系在一起. 举个例子,组件A中有类ClassA,组件B中有接口IB和其对应的实现类B1和B2. 那么,现在ClassA需要利用IB接口来做一些事情,例如: public class ClassA { public void DoSomething() { IB b = ??? b.DoWork(); }} 现

PHP关于依赖注入(控制反转)的解释和例子说明

PHP关于依赖注入(控制反转)的解释和例子说明 发表于2年前(2014-03-20 10:12)   阅读(726) | 评论(1) 8人收藏此文章, 我要收藏 赞2 阿里云双11绽放在即 1111 元红包即刻开抢!»   摘要 自从听到依赖注入这个设计模式,感觉很高大上,无奈楼主的眼光一直局限在国内框架上,也很少去关注设计模式方面的文章,直到某天遇到了laravel后,发现它手册里重点强调了一个名为“依赖注入”和“容器”的概念,但是对于这两个概念,手册里并未做基本的解释,所以楼主只能另外查找相

IoC 依赖注入、以及在Spring中的实现

资源来自网络: 去年火得不行的Spring框架,一般的书籍都会从IoC和AOP开始介绍起,这个IoC概念,个人感觉资料里都写得让人看得有些痛苦,所谓IoC,就是控制反转(Inversion of Control)的缩写,这个大家都知道,但是个人觉得理解这个概念,最好应该从依赖(dependence)开始讲起,以下观点由此展开: UML中依赖关系如A依赖于B,就是A中有对方的引用;也就是说依赖就是引用:A依赖于B,就是A使用B来做事情. 所谓依赖,举个例子说明,一个类Person,另一个类Car,

Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

我们常常会遇到这样一种情景.就是在我们开发项目的时候常常会在一个类中调用其它的类中的方法,来完毕我们期望的任务.大部分的情况下往往会採用在当前需要的这个类里面new一个实例出来.然后调用他的方法,那么这种话会有个问题.就是有一天我想改变下这个类,改为其它的名称.那么这时候必需要做的是同一时候去调用方的类文件里改变这个改变的类的名称.这种情况是由于代码的耦合带来了后期维护成本的添加,那么spring的出现就能够非常好的起到解耦的作用,而他的核心机制就是依赖注入. 依赖注入与控制反转 依赖注入:对于

分层,工厂模式,依赖注入控制反转

1.分层:就如同一个人自己制造一个锤子,自己动手丰衣足食.你需要他就自己new一个该实例.无法实现二者之间的松耦合 2.工厂模式:一个人需要一个锤子,他找工厂,工厂帮他造了一个锤子.工厂给你制造的锤子,但是如何造的你不需要知道.你直接调用该接口就可以了,具体你不需要知道.调用者无须关心被调用者具体实现过程,只需要找到符合某种标准(接口)的实例,即可使用 3.依赖注入:一个人需要一个锤子,他打电话给卖锤子的叫他送货上门.你喜欢哪家的锤子,直接叫哪家送货上门就OK.用者无须自己定位工厂,程序运行到需

大话依赖倒置?控制反转?依赖注入?面向接口编程

那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些“高深术语”感到过困扰——依赖倒置•控制反转•依赖注入•面向接口编程.也许时至今日,你仍对它们一知半解.不过就在今天,这一切都将彻底改变!我将带领你以一种全新的高清视角进入奇妙的编程世界,领略涵泳在这些“高深术语”中的活泼泼的地气,以及翩跹于青萍之末的云水禅心. ·内聚 内聚,通俗的来讲,就是自己的东西自己保管,自己的事情自己做. 经典理论告诉我们,程序的两大要素:一个是数据(data),

控制反转和spring在项目中可以带来的好处

Spring实例化Bean的三种方式分别是: 1,xml配置使用bean的类构造器 <bean id="personService" class="cn.service.impl.PersonServiceBean"></bean> 2,xml配置+factory类,使用静态工厂方法实例化 <bean id="personService2" class="cn.service.impl.PersonServ

动手造轮子:实现一个简单的依赖注入(一)

动手造轮子:实现一个简单的依赖注入(一) Intro 在上一篇文章中主要介绍了一下要做的依赖注入的整体设计和大概编程体验,这篇文章要开始写代码了,开始实现自己的依赖注入框架. 类图 首先来温习一下上次提到的类图 服务生命周期 服务生命周期定义: public enum ServiceLifetime : sbyte { /// <summary> /// Specifies that a single instance of the service will be created. /// &