zoukankan      html  css  js  c++  java
  • 转:深入浅出spring IOC中四种依赖注入方式

    转:https://blog.csdn.net/u010800201/article/details/72674420

    深入浅出spring IOC中四种依赖注入方式

    PS:前三种是我转载的,第四种是现加的,按照原来的代码模式
    spring 的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖 查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入和控制反转是一样的概念吗?接触新的知识,小编的脑袋中全是大大的问号,不过没有关系,今 天这篇博文,小编主要来简单的介绍一下在spring IOC中依赖注入的方法。
    依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性。我们可以从以下几个方面理解:
    a、参与者都有谁?
    b、依赖:谁依赖谁?为什么需要依赖?
    c、注入:谁注入谁?又注入了什么呢?
    d、控制反转:谁控制谁?控制什么?为什么叫反转呢?存在正转吗?

    e、控制反转和依赖注入是同一个概念吗?我们需要弄明白上面的问题,这样对于控制反转和依赖注入的理解有大大的帮助。

    首先:第一个问题,参与者都有谁?
    1)对象
    2)IOC/DI容器
    3)某个对象的外部资源
    第二问题:依赖,谁依赖谁?为什么需要依赖?
    依赖嘛,很好理解的,对象依赖于IOC/DI容器,至于为什么要依赖呢?对象需要IOC/DI容器来提供对象需要的外部资源。
    第三个问题:注入,谁注入谁?又注入了什么呢?
    显而易见是IOC/DI容器注入对象,注入了what呢?肯定注入的是某个需要的东西那就是注入对象所需要的资源,肯定不会注入无关紧要的内容,你说呢?
    第四个问题:控制反转,谁控制谁?控制什么?为什么叫反转呢?存在正转吗?
    控 制反转,控制什么?肯定是IOC/DI容器控制对象,主要是控制对象实例的创建,反转是相对于正向而言的,那么什么算是正向的呢?考虑一下常规情况下的应 用程序,如果要在A里面使用C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C,这种情况被称为正向的。那 么什么是反向呢?就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中。
    第五个问题:控制反转和依赖注入式同一个概念吗?
    依 赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用 程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要 的外部资源。

    了解了这些基本的概念,弄明白她们之间的联系和区别,能够帮助我们更好的理解,接着小编来重点介绍一下依赖注入,在spring ioc中有三种依赖注入,分别是:
    a、接口注入;
    b、setter方法注入;
    c、构造方法注入;

    d、注解方法注入;
    接着小编对这四种注入方式一一进行讲解,通过demo的讲解,希望能够帮助小伙伴们更好的理解,不足之处还请多多指教。
    接口注入

    [java] view plain copy
     
     
     
     在CODE上查看代码片派生到我的代码片
     
    1. public class ClassA {  
    2.   private InterfaceB clzB;  
    3.   public void doSomething() {  
    4.     Ojbect obj = Class.forName(Config.BImplementation).newInstance();  
    5.     clzB = (InterfaceB)obj;  
    6.     clzB.doIt();   
    7.   }  
    8. ……  
    9. }  
    解 释一下上述的代码部分,ClassA依赖于InterfaceB的实现,我们如何获得InterfaceB的实现实例呢?传统的方法是在代码中创建 InterfaceB实现类的实例,并将赋予clzB.这样一来,ClassA在编译期即依赖于InterfaceB的实现。为了将调用者与实现者在编译 期分离,于是有了上面的代码。我们根据预先在配置文件中设定的实现类的类名(Config.BImplementation),动态加载实现类,并通过 InterfaceB强制转型后为ClassA所用,这就是接口注入的一个最原始的雏形。

    setter方法注入

    setter注入模式在实际开发中有非常广泛的应用,setter方法更加直观,我们来看一下spring的配置文件:

    [java] view plain copy
     
     
     
     在CODE上查看代码片派生到我的代码片
     
    1. <?xml version="1.0" encoding="UTF-8"?>    
    2. <beans xmlns="http://www.springframework.org/schema/beans"    
    3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    4.          xmlns:aop="http://www.springframework.org/schema/aop"    
    5.          xmlns:tx="http://www.springframework.org/schema/tx"    
    6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd    
    7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd    
    8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">    
    9.     
    10.     <!-- 使用spring管理对象的创建,还有对象的依赖关系 -->    
    11.     <bean id="userDao4Mysql" class="com.tgb.spring.dao.UserDao4MysqlImpl"/>    
    12.     
    13.     <bean id="userDao4Oracle" class="com.tgb.spring.dao.UserDao4OracleImpl"/>    
    14.         
    15.     <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">    
    16.         <!-- (1)userManager使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理-->    
    17.         <!-- (2)在UserManager中提供构造函数,让spring将UserDao实现注入(DI)过来 -->    
    18.         <!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 -->    
    19.     
    20.         <property name="userDao" ref="userDao4Oracle"></property>    
    21.     </bean>    
    22.         
    23. </beans>    
    24.  
    接着我们来看一下,setter表示依赖关系的写法
    [java] view plain copy
     
     
     
     在CODE上查看代码片派生到我的代码片
     
    1. import com.tgb.spring.dao.UserDao;    
    2.     
    3. public class UserManagerImpl implements UserManager{    
    4.     
    5.     private UserDao userDao;    
    6.     
    7.     //使用设值方式赋值    
    8.     public void setUserDao(UserDao userDao) {    
    9.         this.userDao = userDao;    
    10.     }    
    11.         
    12.     @Override    
    13.     public void addUser(String userName, String password) {    
    14.     
    15.         userDao.addUser(userName, password);    
    16.     }    
    17. }    
    构造器注入

    构造器注入,即通过构造函数完成依赖关系的设定。我们看一下spring的配置文件:

    [java] view plain copy
     
     
     
     在CODE上查看代码片派生到我的代码片
     
    1. <?xml version="1.0" encoding="UTF-8"?>    
    2.     <beans xmlns="http://www.springframework.org/schema/beans"    
    3.              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    4.              xmlns:aop="http://www.springframework.org/schema/aop"    
    5.              xmlns:tx="http://www.springframework.org/schema/tx"    
    6.              xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd    
    7.                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd    
    8.                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">    
    9.         
    10.         <!-- 使用spring管理对象的创建,还有对象的依赖关系 -->    
    11.         <bean id="userDao4Mysql" class="com.tgb.spring.dao.UserDao4MysqlImpl"/>    
    12.         
    13.         <bean id="userDao4Oracle" class="com.tgb.spring.dao.UserDao4OracleImpl"/>    
    14.             
    15.         <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">    
    16.             <!-- (1)userManager使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理-->    
    17.             <!-- (2)在UserManager中提供构造函数,让spring将UserDao实现注入(DI)过来 -->    
    18.             <!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 -->    
    19.         
    20.             <constructor-arg ref="userDao4Oracle"/>    
    21.         </bean>    
    22.             
    23.     </beans>    
    我们再来看一下,构造器表示依赖关系的写法,代码如下所示:
    [java] view plain copy
     
     
     
     在CODE上查看代码片派生到我的代码片
     
    1.  import com.tgb.spring.dao.UserDao;    
    2.         
    3.     public class UserManagerImpl implements UserManager{    
    4.         private UserDao userDao4Oracle;
    5.         
    6.         //使用构造方式赋值    
    7.         public UserManagerImpl(UserDao userDao4Oracle) {    
    8.             this.userDao4Oracle = userDao4Oracle;    
    9.         }    
    10.         
    11.         @Override    
    12.         public void addUser(String userName, String password) {    
    13.         
    14.             userDao.addUser(userName, password);    
    15.         }    
    16.     }    
    注解注入

    注解注入,即通过注解方式完成依赖关系的设定。我们看一下spring的配置文件:

    [java] view plain copy
     
     
     
     在CODE上查看代码片派生到我的代码片
     
    1. <?xml version="1.0" encoding="UTF-8"?>    
    2. <beans xmlns="http://www.springframework.org/schema/beans"    
    3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    4.          xmlns:aop="http://www.springframework.org/schema/aop"    
    5.          xmlns:tx="http://www.springframework.org/schema/tx"    
    6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd    
    7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd    
    8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">    
    9.   

      <context:annotation-config/>//启动spring注解模式

        
    10.     <!-- 使用spring管理对象的创建,还有对象的依赖关系 -->    
    11.     <bean id="userDao4Mysql" class="com.tgb.spring.dao.UserDao4MysqlImpl"/>    
    12.     
    13.     <bean id="userDao4Oracle" class="com.tgb.spring.dao.UserDao4OracleImpl"/>    
    14.         
    15.     <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">    
    16.         <!--<property name="userDao" ref="userDao4Oracle"></property> --> //这段去掉  
    17.     </bean>    
    18.         
    19. </beans>    
    20.  
     
    具体写法:
    1. import com.tgb.spring.dao.UserDao;  
    2.  import javax.annotation.Resource;  //需要导入相关jar包
    3.         
    4.     @Resource(name="userDao4Oracle")
    5.      private UserDao userDao4Oracle;
    6.     
    7.      public class UserManagerImpl implements UserManager{    
    8.         private UserDao userDao4Oracle;
    9.         
    10.         
    11.         @Override    
    12.         public void addUser(String userName, String password) {    
    13.         
    14.             userDao.addUser(userName, password);    
    15.         }    
    16.     }    

    接口注入 && setter注入 && 构造器注入
            接口注入:
    接口注入模式因为具备侵入性,它要求组件必须与特定的接口相关联,因此并不被看好,实际使用有限。
    Setter 注入:
    对 于习惯了传统 javabean 开发的程序员,通过 setter 方法设定依赖关系更加直观。如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。如果用到了第三方类库,可 能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。
    构造器注入:
    在构造期间完成一个完整的、合法的对象。所有依赖关系在构造函数中集中呈现。依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。
    注解注入:@Resource先会按照名称到spring容器中查找,如果查找不到,就回退按照类型匹配,如果再没有匹配到,就会抛出异常。如果在开发的时候,建议大家都是用@Resource(name=”userDao”),此时只能够按照名称匹配

    小编寄语:该 博文,小编主要介绍了控制反转、依赖注入以及在spring中IOC的三种注入方式,配上demo进行讲解,不足之处,还请各位小伙伴多多指教,其实小编 觉得,无论是控制反转还是依赖注入对编程带来最大的影响不是从代码上,而是思想上转变,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都 是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC/DI容器来创建并注入她所需要的资源了。这一举动,有效的分离了对象 和她所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

  • 相关阅读:
    ASP.NET Core 中文文档 第四章 MVC(3.2)Razor 语法参考
    ASP.NET Core 中文文档 第四章 MVC(3.1)视图概述
    ASP.NET Core 中文文档 第四章 MVC(2.3)格式化响应数据
    ASP.NET Core 中文文档 第四章 MVC(2.2)模型验证
    ASP.NET Core 中文文档 第四章 MVC(2.1)模型绑定
    ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览
    mysql 解除正在死锁的状态
    基于原生JS的jsonp方法的实现
    HTML 如何显示英文单、双引号
    win2008 r2 服务器php+mysql+sqlserver2008运行环境配置(从安装、优化、安全等)
  • 原文地址:https://www.cnblogs.com/zhanglijun/p/9140820.html
Copyright © 2011-2022 走看看