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实例时,已经完毕了依赖关系。

二十7天 春雨滋润着无形 —Spring依赖注入的更多相关文章

  1. 二十、MVC的WEB框架(Spring MVC)

    一.Spring MVC 运行原理:客户端请求提交到DispatcherServlet,由DispatcherServlet控制器查询HandlerMapping,找到并分发到指定的Controlle ...

  2. Spring 依赖注入(二、注入参数)

    注入参数基本分7类: 1.基本类型值 2.注入bean 3.内部bean 4.注入null值 5.级联属性 6.List,Set,Map集合的注入 7.properties文件的注入(和集合注入基本是 ...

  3. 【10分钟学Spring】:(二)一文搞懂spring依赖注入(DI)

    Spring最基础的特性就是创建bean.管理bean之间的依赖关系.下面通过具体实例演示该如何装配我们应用中的bean. Spring提供了三种主要的装配机制 在xml中进行显示的配置 在Java中 ...

  4. SpringBoot进阶教程(二十六)整合Redis之共享Session

    集群现在越来越常见,当我们项目搭建了集群,就会产生session共享问题.因为session是保存在服务器上面的.那么解决这一问题,大致有三个方案,1.通过nginx的负载均衡其中一种ip绑定来实现( ...

  5. WCF学习之旅—第三个示例之三(二十九)

    上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) 在上一篇文章中我们创建了实体对象与接口协定,在这一篇文章中我们来学习如何创建WCF的服务端代码.具体步骤见下面. ...

  6. WCF学习之旅—TcpTrace工具(二十六)

    止文(WCF学习之旅—TcpTrace工具(二十五))介绍了关于TcpTrance的一种使用方式,接下来介绍第二种使用方式. 三.通过ListenUri实现基于tcpTracer的消息路由 对于路由的 ...

  7. WCF学习之旅—实现支持REST客户端应用(二十四)

    WCF学习之旅—实现REST服务(二十二) WCF学习之旅—实现支持REST服务端应用(二十三) 在上二篇文章中简单介绍了一下RestFul与WCF支持RestFul所提供的方法,及创建一个支持RES ...

  8. geotrellis使用(二十五)将Geotrellis移植到spark2.0

    目录 前言 升级spark到2.0 将geotrellis最新版部署到spark2.0(CDH) 总结 一.前言        事情总是变化这么快,前面刚写了一篇博客介绍如何将geotrellis移植 ...

  9. geotrellis使用(二十二)实时获取点状目标对应的栅格数据值

    目录 前言 实现方法 总结 一.前言        其实这个功能之前已经实现,今天将其采用1.0版的方式进行了重构与完善,现将该内容进行总结.        其实这个功能很常见,比如google地球上 ...

随机推荐

  1. 怎么用CIFilter给图片加上各种各样的滤镜_1

    近期在做对图像处理的app,而要对图像进行处理,CoreImage是离不开的框架. 上网Google了一下,大部分的博客都是仅仅讲了怎么给图像加上怀旧(CISepiaTone).模糊(CIBloom) ...

  2. JavaScript之面向对象1

    学习过Java程序的开发人员都知道面向对象是怎么回事. 面向对象无非就是封装.多态.继承 比如: 声明一个类: class Person{ //私有成员 private String name; pr ...

  3. ZOJ3805:Machine

    In a typical assembly line, machines are connected one by one. The first machine's output product wi ...

  4. Virtualbox mouse move in and out and file share with windows

    How to use Virstalbox to share files with Linux and Windows, and to move the mouse in and out Virtua ...

  5. memwatch的使用

    博主的新Blog地址:http://www.brantchen.com 欢迎訪问:) linux下的測试工具真是少之又少,还不好用,近期试用了memwatch,感觉网上的介绍不太好,所以放在这里跟大家 ...

  6. 初始化openwrt的rootpassword

    更改openwrt源代码 shadow 文件 package/base-files/files/etc/shadow shadow 文件參考http://blog.csdn.net/u01164188 ...

  7. hdu4223(dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4223 由于n范围较小,完全可暴力... #include <cstdio> #includ ...

  8. Android数据库高手秘籍(一)——SQLite命令

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/38461239 要想熟练地操作不论什么一个数据库.最最主要的要求就是要懂SQL语言, ...

  9. TopCoder SRM 625 Incrementing Sequence 题解

    本题就是给出一个数k和一个数组,包含N个元素,通过每次添加�数组中的一个数的操作,最后须要得到1 - N的一个序列,不用排序. 能够从暴力法入手,然后优化. 这里利用hash表进行优化,终于得到时间效 ...

  10. 新浪SAE数据库信息

    此账号仅能在SAE平台上使用,不能从外部连接我们建议开发者使用SaeMysql操作数据库 如果您想自己实现数据库相关操作,可以使用以下常量: 用户名  : SAE_MYSQL_USER 密 码 : S ...