zoukankan      html  css  js  c++  java
  • Spring三大核心思想之二:DI

    Spring三大核心思想之二:DI

     spring第二个特性是依赖注入。

             学习依赖注入,首先应该明白两个问题:1,谁依赖谁;2,谁注入,注入什么?

             首先还是看代码:

             还是这个bean:

    Java代码  收藏代码
    1. package testSpring.business.bean;  
    2.   
    3. import org.springframework.stereotype.Repository;  
    4.   
    5. import testSpring.business.iface.IPrint;  
    6.   
    7. /**   
    8.  *  UserBean :  
    9.  * @author xuejupo  jpxue@travelsky.com  
    10.  * create in 2016-2-16 上午9:22:39     
    11.  */  
    12. public class UserBean implements IPrint{  
    13.     @Override  
    14.     public String printObject() {  
    15.         // TODO Auto-generated method stub  
    16.         System.out.println("打印对象UserBean:");  
    17.         return "abc";  
    18.     }  
    19.   
    20. }  

     然后,我的业务逻辑需要在这个bean里使用上边那个bean:

    Java代码  收藏代码
    1. package testSpring.business.impl;  
    2.   
    3. import testSpring.business.iface.IPrint;  
    4.   
    5. /**   
    6.  *  Print :  
    7.  * @author xuejupo  jpxue@travelsky.com  
    8.  * create in 2016-2-16 上午10:23:37     
    9.  */  
    10.   
    11. public class Print {  
    12.     //需要打印的bean,注入的入口(需要注入的对象)  
    13.     private IPrint printBean;  
    14.     private String name;  
    15.     public void print(){  
    16.         System.out.println("注入的name:"+name);  
    17.         this.printBean.printObject();  
    18.     }  
    19.       
    20.     /**   
    21.     * setPrintBean: set方法,set注入必备方法 
    22.     * @param printBean  
    23.     * void  返回类型    
    24.     */  
    25.     public void setPrintBean(IPrint printBean){  
    26.         this.printBean = printBean;  
    27.     }  
    28.       
    29.     /**   
    30.     * setName: set方法,set注入必备方法 
    31.     * @param name  
    32.     * void  返回类型    
    33.     */  
    34.     public void setName(String name){  
    35.         this.name = name;  
    36.     }  
    37. }  

         普通的使用print类的客户端代码:

    Java代码  收藏代码
    1. Print p = new Print();  
    2. p.setPrintBean(new UserBean());  
    3. print.print();  

         也是挺简单的代码,但是,客户端代码就和具体的类print和userbean的代码强耦合在一块了,不符合开闭原则,所以就需要利用依赖注入往客户端代码中注入Pring对象,往Print类中注入Userbean对象。

            xml文件如下:

    Java代码  收藏代码
    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" xmlns:tx="http://www.springframework.org/schema/tx"  
    4.     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"  
    5.     xmlns:p="http://www.springframework.org/schema/p"  
    6.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
    7.     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
    8.     http://www.springframework.org/schema/tx  
    9.     http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  
    10.     http://www.springframework.org/schema/aop    
    11.     http://www.springframework.org/schema/aop/spring-aop-3.2.xsd   
    12.     http://www.springframework.org/schema/context  
    13.     http://www.springframework.org/schema/context/spring-context-3.2.xsd">  
    14.     <context:annotation-config/>  
    15.     <!-- 注册javabean -->  
    16.     <bean id="userBean" class="testSpring.business.bean.MyBean" />  
    17.       
    18.     <!-- 注册javabean -->  
    19.     <bean id="printBean" class="testSpring.business.impl.Print" >  
    20.     <!-- 注入javabean中的参数 -->  
    21.         <property name = "printBean" ref = "userBean"></property>  
    22.         <property name = "name" value = "haha"></property>  
    23.     </bean>  
    24. </beans>  

     客户端代码:

    Java代码  收藏代码
    1. //读取配置文件(将配置文件中的bean加载进内存)  
    2.         ApplicationContext ctx = new ClassPathXmlApplicationContext("/testSpring/resources/applicationContext.xml");  
    3.         //获取的实例  
    4.         Print bean=(Print)ctx.getBean("printBean");    
    5.         //调用方法    
    6.         bean.print();  

     打印结果:

    Java代码  收藏代码
    1. 注入的name:haha  
    2. 打印对象MyBean:  

           可以看到,利用xml的配置信息,在客户端代码中不用具体new任何的java对象了,java对象的创建工作,和对象中元素的赋值工作可以交给xml(spring)处理。

            回答文中开头两个问题:1.客户端代码中,具体对象的创建依赖于xml文件(spring,即IOC容器);2.是IOC容器注入,在运行期,根据xml的配置信息,将具体的对象注入到相应的bean中。

           说一下自己理解中的IOC容器: 网上搜过,没有什么让我满意的回答,只能自己理解一下。我理解的IOC容器,其实就是web服务启动后,tomcat(或其他的web服务器)加载applicationContext.xml(注册bean的spring配置文件),会在内存中开辟一块内存区域专门存储在xml文件中加载的bean,并且是以map映射的形式存储的,key是id,value就是具体的bean。这块内存区域,用于存储bean的容器,就叫IOC容器(其实更应该叫spring的bean容器)(个人理解,实在找不到对这个定义比较好的解释,只能先这么理解了)。

            如果看过我前一篇博客的,肯定会说依赖注入和控制反转这不一样嘛。。。。他俩确实是一回事。。。依赖注入也可以叫控制反转,就是将控制权交给配置文件。。   不过我个人喜欢这样理解:对bean的注册叫控制反转,对bean中参数的初始化叫依赖注入。个人觉得,知道是一回事就行,怎么容易让你理解怎么来。

           说一下依赖注入的好处:

           最主要的还是解耦。便于数据源的切换:比如我想在print类里打印另一个bean,只需要修改xml文件即可。

           这说的还是有点虚,可能真实环境更能说明问题:   公司最近遇到一个需求,需要两拨人共同开发:一波开发公司内网接口---A组,一波开发公司对外实现(相当于客户端)---B组。客户端开发是依赖于内网功能的,但是又不能等待内网的同学先开发完,所以领导决定:A组的人,先把需要实现的功能,以接口(interface)的方式暴漏给B组的同学,然后两组各自为政,开发完以后合并就行了。

            假设A组暴漏了一个接口如下:

    Java代码  收藏代码
    1. public interface MyInterface{  
    2.         void myMethod();  
    3. }  

            但是A组这个接口的实现还没写,所以我B组的人想用这个接口编程,两个办法(我是菜鸟,可能有别的办法,可以指点):

            第一:

    Java代码  收藏代码
    1. MyInterface  bean = null;//这里需要后期填充具体接口实现  

            然后,当A组的把实现给我们之后,我们再通过全局搜索,把bean全都赋值给具体的实现。这时候,万一A组的人脑子一抽,说哎呀,我给你的实现不对,是应该给C组的,你用另一个,那我又要全局修改所有的代码。。。。(这就是强耦合,A组修改代码,会导致B组人代码必须修改)

            然后,第二种是酱:

             用一个配置文件:

    Java代码  收藏代码
    1. <bean id="myInterface" class="xxx.xxx.xxx.xxxx" />  
    2. <!-- 注册我的javabean -->  
    3.     <bean id="printBean" class="testSpring.business.impl.Print" >  
    4.     <!-- 注入接口实现 -->  
    5.         <property name = "myInterface" ref = "myInterface"></property>  
    6.     </bean>  

         然后在我已经注册的javaBean里只需要这样:

    Java代码  收藏代码
    1. private MyInterface myInterface;  

         就可以使用接口的具体实现了,而且无论你A组怎么改,我B组的代码不用修改,只改配置文件就行(当然,前提是A组的接口不能变),这就是弱耦合,也是设计原则里面著名的依赖倒置原则(依赖接口而不依赖于具体实现)。

    抱怨没有用,只能靠自己
  • 相关阅读:
    使用homebrew安装mysql
    MacOS下命令行安装神器brew
    mac Navicat 破解+汉化(亲测可用)
    eos开发(三)使用cleos命令行客户端操作EOS——关于钱包wallet和账户account
    eos开发(二)使用cleos命令行客户端操作EOS(钱包wallet基础操作)
    php职业规划
    temp
    事业随想
    系统时间错误
    加解密,token
  • 原文地址:https://www.cnblogs.com/mybatis/p/8985882.html
Copyright © 2011-2022 走看看