zoukankan      html  css  js  c++  java
  • 二十7天 春雨滋润着无形 —Spring依赖注入

                  6月11日,明确。“夏条绿已密,朱萼缀明鲜。炎炎日正午,灼灼火俱燃。”

            IT人习惯把详细的事物加工成的形状一致的类。正是这种一致,加上合适的规范。才干彰显对象筋道的牙感和bean清香的味道。

    Spring比谁都清楚OO的奥妙,让组件之间的依赖关系由容器在执行时期决定,称作依赖注入(Dependency Injection)。

               以下用一通俗的样例,一探依赖注入奥妙。

           设计模式中的一个原则:针对接口编程。不要针对实现编程。

                 一、设计两个接口:

              (1)奶制品接口—MilkProductInterface.java                               

    package edu.eurasia.IOC;
    
    public interface MilkProductInterface {
       public void drinkMilk();
       public void eatCheese();
    }
                    (2)奶制品接口的实现类—Milk.java

    package edu.eurasia.IOC;
    
    public class Milk implements MilkProductInterface {
    	
    	public void drinkMilk() {
    		System.out.println("新奇的牛奶真好喝!

    "); } public void eatCheese() { System.out.println("仅仅有鲜奶,无奶酪o(╯□╰)o"); } }

             (3)奶制品接口的实现类—Cheese.java

    package edu.eurasia.IOC;
    
    public class Cheese implements MilkProductInterface {
    
    	public void drinkMilk() {
    		System.out.println("仅仅有奶酪。无鲜奶o(╯□╰)o");
    
    	}
    
    	public void eatCheese() {
    		System.out.println("发酵后的美味奶酪真好吃!

    "); } }

             (4)人的接口—PersonInterface.java        

    package edu.eurasia.IOC;
    
    public interface PersonInterface {
    	public void drink();
    	public void eat();
    }
            (5)人接口的实现类—Person.java

             正常情况下,人要喝牛奶。吃奶酪。这样写就ok了。

    package edu.eurasia.IOC;
    
    public class Person implements PersonInterface {
    	public void drink() {
    		MilkProductInterface milk = new Milk();
    		milk.drinkMilk();
    	}
    
    	public void eat() {
    		MilkProductInterface cheese = new Cheese();
    		cheese.eatCheese();
    	}
    }
    
          (6)測试类—TestIOC.java
    package edu.eurasia.IOC;
    
    import org.junit.Test;
    
    public class TestIOC {
    	@Test
    	public void eatdrink(){
    	   PersonInterface p = new Person();
        	   p.drink();
        	   p.eat();    	
    	}
    }
            结果输出:新奇的牛奶真好喝!

                         发酵后的美味奶酪真好吃。

             上述代码。非常多刚開始学习的人看不出来有什么问题。可是。类是一样的类。一“new”见高下。使用“new”的时候,就已经在实例化一个详细类了,这就是一种实现,仅仅要有详细类的出现。就会导致代码更缺乏弹性。

    重温设计模式中的一个原则:针对接口编程。不要针对实现编程

             简单的说依赖注入的思想常见的一种情况:假设一个类中要复用另外一个类中的功能时,可能会首先想到继承,假设知道Ioc这样的思想的话,就不会用继承,会立即想到把要用到功能抽取出来,在我们要用到的类中仅仅需通过set方法简单的注入就能够了,事实上这里用到了对象的组合取代继承。这样不仅避免了单一继承,还非常好的实现了松耦合。同一时候也遵循了面向对象的编程的设计原则:多用组合,少用继承。


               二、依赖注入(Set):                 

               (1)改动人接口的实现类—Person.java

    package edu.eurasia.IOC;
    
    public class Person implements PersonInterface {
    	private MilkProductInterface milkX;
    
    	public void setMilkX(MilkProductInterface milkX) {
    		this.milkX = milkX;
    	}
    
    	@Override
    	public void drink() {
    		milkX.drinkMilk();
    	}
    
    	@Override
    	public void eat() {
    		milkX.eatCheese();
    
    	}
    }
    

                  声明一个MilkProductInterface接口变量milkX这个milkX代表随意一种详细的奶制品,可能是牛奶milk,也可能是奶酪cheese,还有可能是奶茶milky tea...总之,我们能够动态的在执行时改变它的详细属性。怎么改?疑问别着急,你发现了milkX的set方法。大笑哈哈,这就是大名鼎鼎的Set注入(setter injection)偷笑

              看到了注入,那么依赖(Dependency)在哪里?    

            我们对着雾霾喊: 依赖。我们的好DI。 你在哪里呵,你在哪里? 你可知道,我们想念你...          
             雾霾翻滚: 它就在配置文件中...

               (2)编写配置文件—applicationContext.xml,放在src以下。

    <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-2.5.xsd">
    	
    	<bean id="milk" class="edu.eurasia.IOC.Milk"></bean>
    	<bean id="cheese" class="edu.eurasia.IOC.Cheese"></bean>
    	
    	<bean id="person" class="edu.eurasia.IOC.Person">
    		<property name="milkX" ref="milk"></property>		
    	</bean>   
    </beans> 

                 配置文件是Spring依赖注入的关键:

            首先,定义两个bean,第一个bean的id是milk, class指定该bean实例的实现类;第二个bean的id是cheese。class相同指定该bean实例的实现类。这两个bean是为以下的Bean提供引用注入的。

           其次,再定义一个bean,bean的id是person, class指定该bean实例的实现类。property元素用来指定须要容器注入的属性,属性名milkX要与Person.java中的属性一致。ref引用要注入的值即上面定义的任一个id。不同的id。就是注入的不同值,因此Person类必须拥有setMilkX方法。说了半天,灵活性就在这里体现了。敲打

          从配置文件中,能够看到Spring管理bean的机灵性。bean与bean之间的依赖关系放在配置文件中组织,而不是写在代码里。

    通过配置文件的 指定,Spring能精确地为每一个bean注入属性。因此,配置文件中的bean的class元素,不能不过接口。而必须是真正的实现类。


          Spring会自己主动接管每一个bean定义里的property元素定义。Spring会在运行无參数的构造器后、创建默认的bean实例后,调用相应的setter方法为注入属性值。

    property定义的属性值将不再由该bean来主动创建、管理,而改为被动接收Spring的注入。
          每一个bean的id属性是该bean的惟一标识,程序通过id属性訪问bean。bean与bean的依赖关系也通过id属性完毕。

          注:

           1、spring配置文件里Bean中的id和name的差别

                  id:鼓舞使用ID属性来标识一个Bean, 不能重名,能够被DTD验证。不能以数字,符号打头,不能有空格;  

             name: 能够重名, 后面的覆盖前面。

          2、JavaBean关于属性命名的特殊规范
            Spring配置文件里<property>元素所指定的属性名和Bean实现类的Setter方法满足Sun JavaBean的属性命名规范:xxx的属性相应setXxx()方法。

            普通情况下。Java的属性变量名都以小写字母开头,如maxSpeed、brand等。但也存在特殊的情况,考虑到一些特殊意义的大写英文缩略词(如USA、XML等),JavaBean也同意大写字母开头的属性变量名,但必须满足“变量的前两个字母要么所有大写,要么所有小写”的要求,如brand、ICCard是合法的,而iCiCCard是非法的。

            (3)改写測试类—TestIOC.java

    package edu.eurasia.IOC;
    
    import org.junit.Test;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    public class TestIOC {
    	@Test
    	public void eatdrink(){
    	    AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");     
    	    Person p =  (Person) context.getBean("person");
    	    p.drink(); 
    	    p.eat();
    	}
    }
    

              程序实例化Spring的上下文,通过Person bean的id来获取bean实例。从而实现面向接口编程。

    结果输出:新奇的牛奶真好喝!

                     仅仅有鲜奶,无奶酪o(╯□╰)o

             更改applicationContext.xml里面的ref="cheese"。

    此时再次运行程序。将得到例如以下结果:
               仅仅有奶酪。无鲜奶o(╯□╰)o
               发酵后的美味奶酪真好吃!

               採用setter方法为目标bean注入属性的方式,称为设值注入。

    此外。另一种叫构造注入。所谓构造注入。指通过构造函数来完毕依赖关系的设定,而不是通过setter方法。

               三、依赖注入(构造):           

            (1)改动人接口的实现类—Person.java

    package edu.eurasia.IOC;
    
    public class Person implements PersonInterface {
    	
    	private MilkProductInterface milkX;
    
    	public Person(MilkProductInterface milkX) {
    		super();
    		this.milkX = milkX;
    	}
    
    	@Override
    	public void drink() {
    
    		milkX.drinkMilk();
    	}
    
    	@Override
    	public void eat() {
    		milkX.eatCheese();
    
    	}
    }
    
            (2)改动配置文件—applicationContext.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-2.5.xsd"> <bean id="milk" class="edu.eurasia.IOC.Milk"></bean> <bean id="cheese" class="edu.eurasia.IOC.Cheese"></bean> <bean id="person" class="edu.eurasia.IOC.Person"> <!-- <property name="milkX" ref="milk"></property> --> <constructor-arg ref="milk"></constructor-arg> </bean> </beans>

                    运行效果与使用设值注入时的运行效果全然一样。差别在于:创建Person实例中属性的时机不同—设值注入是现创建一个默认的bean实例,然后调用相应的构造方法注入依赖关系。

    而构造注入则在创建bean实例时,已经完毕了依赖关系。

                  




                

  • 相关阅读:
    网页a标签:导航制作 怎么让鼠标经过A标签的时候显示块状背景?
    从头开始,慢慢来,今天工作日志
    想看所有的美国系列电影
    百分比宽度并排元素浮动之后,设置margin,padding换行的问题
    TP5.1 首页路由
    关于Layui 响应式移动端轮播图的问题
    BootStrap 栅格化换行问题
    VS code 格式化插件, 仅需一步, 无须配置
    PHPStorm 批量选择,多光标同时编辑相同的内容
    使用Cmder 安装 Composer 出现 "attempt to call a nil value"
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5031897.html
Copyright © 2011-2022 走看看