zoukankan      html  css  js  c++  java
  • [译]12-spring依赖注入

    每个java应用程序都是由多个类协作才最终生成了终端用户所使用的系统.当编写复杂java应用程序的时,类之间应尽

    可能保持独立,因为这样更容易做到代码的重用,也有利于单元测试的开展.spring的依赖注入功能能在保持类相互独立

    的同时把他们"粘合"起来.

    考虑如下场景:你的应用程序中有个文本编辑器组件,你现在想给你的文本编辑器添加拼写检查的功能.那么你可能写

    出如下的代码来:

    public class TextEditor {
       private SpellChecker spellChecker;
       
       public TextEditor() {
          spellChecker = new SpellChecker();
       }
    }

    在上述大代码中TextEditor类中聚合了SpellChecker类,这里我们称SpellChecker为TextEditor类的依赖项.而且依

    赖项实例化的工作是在TextEditor内部完成的。这种看似理所当然的代码,其实是有相当大的问题的.这里直接实例化

    SpellChecker类.而在实际应用中,拼写检查工具会有不同的实现,如果我们想切换TextEditor的SpellChecker的实现

    类就必须修改代码。

    在使用了控制反转框架之后,写出的代码会是如下这样:

    public class TextEditor {
       private SpellChecker spellChecker;
       
       public TextEditor(SpellChecker spellChecker) {
          this.spellChecker = spellChecker;
       }
    }

    在这段代码中SpellChecker是通过TextEditor的构造器传入的.TextEditor不必关心SpellChecker的实现.具体的实

    现类是由spring容器在实例化的TextEditor的时候注入的.

    由于TextEditor对依赖项SpellChecker的控制权从TextEditor转移到了spring容器,即控制权发生了反转.控制权发

    生反转的方式是通过依赖注入(原理是Java的反射)来实现的.

    spring中依赖注入的方式有两种:

    1. 通过bean的构造器参数进行注入
    2. 通过bean的setter方法进行依赖注入.实例化bean之后,spring容器会反射调用bean的setter方法.

    下面我们将分别讲解着两种依赖注入的方式。

    构造器参数进行依赖注入

    使用构造器参数进行依赖注入,spring容器会在实例化bean的时候把bean的依赖项通过bean的带参的构造函数进行

    注入.下面用一个例子进行演示:

    1.创建包com.tutorialspoint.di,并在包内新建TextEditor.java和SpellChecker.java,内容分别如下:

    TextEditor.java如下:

    package com.tutorialspoint.di;
    
    public class TextEditor {
        
        private SpellChecker spellChecker;
    
        public TextEditor(SpellChecker spellChecker) {
            System.out.println("Inside TextEditor constructor.");
            this.spellChecker = spellChecker;
        }
    
        public void spellCheck() {
            spellChecker.checkSpelling();
        }
    }

    SpellChecker.java如下:

    package com.tutorialspoint.di;
    
    public class SpellChecker {
        
        public SpellChecker() {
            System.out.println("Inside SpellChecker constructor.");
        }
    
        public void checkSpelling() {
            System.out.println("Inside checkSpelling.");
        }
    
    }

    2.在src目录下新建di.xml配置文件,文件内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <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-3.0.xsd">
    
       <bean id="textEditor" class="com.tutorialspoint.di.TextEditor">
          <constructor-arg ref="spellChecker"/>
       </bean>
    
       <bean id="spellChecker" class="com.tutorialspoint.di.SpellChecker"/>
    
    </beans>

    3.在包com.tutorialspoint.di中新建MainApp.java,内容如下:

    package com.tutorialspoint.di;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
        
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("di.xml");
    
            TextEditor te = (TextEditor) context.getBean("textEditor");
    
            te.spellCheck();
            
        }
    }

    4.运行程序,检查结果:

    使用构造器参数进行依赖项的注入,有时候会产生歧义.这时候可以使用type属性进行歧义的消除.

    set方法依赖注入

    spring也可以使用set方法进行依赖注入.当bean实例化以后,spring容器会反射调用bean实例的set方法进行依赖项

    的注入.在基于xml的配置文件中可以使用bean元素的property子元素指定需要使用setter进行注入的依赖项.

    下面看个例子

    1.创建包com.tutorialspoint.di.setter.并在包中新建TextEditor.java和SpellChecker.java,内容分别如下:

    TextEditor.java

    package com.tutorialspoint.di.setter;
    
    public class TextEditor {
        
        private SpellChecker spellChecker;
    
        public void setSpellChecker(SpellChecker spellChecker) {
            System.out.println("Inside setSpellChecker.");
            this.spellChecker = spellChecker;
        }
    
        public void spellCheck() {
            spellChecker.checkSpelling();
        }
    }

     SpellChecker.java

    package com.tutorialspoint.di.setter;
    
    public class SpellChecker {
        
        public SpellChecker() {
            System.out.println("Inside SpellChecker constructor.");
        }
    
        public void checkSpelling() {
            System.out.println("Inside checkSpelling.");
        }
    
    }

    2.在src目录下新建di_setter.xml配置文件,内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <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-3.0.xsd">
    
       <bean id="textEditor" class="com.tutorialspoint.di.setter.TextEditor">
          <property name="spellChecker" ref="spellChecker"/>
       </bean>
    
       <bean id="spellChecker" class="com.tutorialspoint.di.setter.SpellChecker"/>
    
    </beans>

     3.在包com.tutorialspoint.di.setter中新建MainApp.java类,内容如下:

    package com.tutorialspoint.di.setter;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("di_setter.xml");
    
            TextEditor te = (TextEditor) context.getBean("textEditor");
    
            te.spellCheck();
        }
    }

    4.运行程序,检查结果:

    setter方法进行依赖注入的xml配置方式支持p命名空间,使用p命名空间可以减少配置文件大小,把di_setter.xml

    修改成如下内容,继续运行程序,发现结果跟上次完全一样:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
       <bean id="textEditor" class="com.tutorialspoint.di.setter.TextEditor" p:spellChecker-ref="spellChecker">
       </bean>
    
       <bean id="spellChecker" class="com.tutorialspoint.di.setter.SpellChecker"/>
    
    </beans>
  • 相关阅读:
    MArkdown使用转
    吴恩达deep learning笔记。
    TCP状态转换图
    TCP关闭的四次握手
    SYN的中发送若干的TCP选项
    Ubuntu系统中切换root用户的命令,总忘了sudo
    logistic regression recap
    二分分类中的logistic回归(regression)
    UNIX下的网络族分类,IPv4和IPv6协议族
    11.8模拟赛
  • 原文地址:https://www.cnblogs.com/sysman/p/4479951.html
Copyright © 2011-2022 走看看