一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) set 注入。这篇随笔讲的是第一种构造方法注入(Constructor Injection).

其实DI(Dependency Injection)依赖注入你不妨反过来读:注入依赖也就是把"依赖"注入到一个对象中去。那么何为"依赖"呢?依赖就是讲一个对象初始化或者将实例化的时候需要另一个对象,我们把另一个对象成为"依赖"。如构造方法注入(Constructor Injection)就是把依赖当做构造方法的参数注入进去的。如:

//Injection B to A. 我们把B称为依赖。一般情况下B是一个接口,这符合面向接口编程的规范。

public A (B b){

}

二:使用依赖注入的好处是什么?

  1.DI(Dependency Injection)最大的好处是decoupling(解耦)。如上面的代码把B注入给A如果B是一个接口或者抽象类。只要任何一个类实现或者继承B都可以注入给A.因此可以达到解耦的目的。

  2. 依赖注入给谁?        

dependencies injected into the objects that need them.(依赖注入给那些需要他们的对象。)

3.在spring中怎么让依赖传入到被依赖的对象(看上面的代码:怎么把B传入到A中)?

 在这里我引用一下spring in action中的一段文字:(注:我下面的示例代码基本跟spring in action 的一样)

The big question here is,how can you give SlayDragonQuest to BraveKnight ? And how can you give a PrintStream to SlayDragonQuest?

The act of creating associations between application components is commonly referred to as wiring.

spring通过配置配置文件,配置bean的形式,完成装配,又装配实现把依赖注入给需要他们的对象中的。

【我这里还想说明一下配置文件中的一个bean其实就对应一个javabean,也就是一个pojo对象,bean就是javabean的缩写形式而已】

示例代码的目录结构如下图所示:

  上面中的带两个圈的配置文件想说明两个问题:

一个是:new ClassPathXmlApplicationContext("spring-julysecond.xml");//注意这个.xml文件是在src目录下。

    new ClassPathXmlApplicationContext("com/config/spring-julythird.xml")//注意这个.xml文件在com.cofig这个文件下。

另一个问题是DI的解耦问题:spring-julysecond.xml文件中注入的是SlayDragonQuest,spring-julythird.xml注入的是SearchHillQuest.在不改变代码的情况下看传入的Quest的实现类不同,从而打出的结果不同。

spring-julysecond.xml的代码如下:

  1. 1 <?xml version="1.0" encoding="UTF-8"?>
  2. 2 <beans xmlns="http://www.springframework.org/schema/beans"
  3. 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. 4 xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. 5 http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. 6 <!--this is constructor injection-->
  7. 7 <!--the act of creating associations between application components is commonly referred to
  8. 8 as wiring-->
  9. 9 <bean id="knight" class="com.qls.impl.BraveKnight">
  10. 10 <!-- collaborators and configuration for this bean go here -->
  11. 11 <constructor-arg ref="query"></constructor-arg>
  12. 12 </bean>
  13. 13 <bean id="query" class="com.qls.impl.SlayDragonQuest">
  14. 14 <!-- collaborators and configuration for this bean go here -->
  15. 15 <constructor-arg value="#{T(System).out}"/>
  16. 16 </bean>
  17. 17 <!-- more bean definitions go here -->
  18. 18 </beans>

//spring-julythird.xml的代码如下:

  1. 1 <?xml version="1.0" encoding="UTF-8"?>
  2. 2 <beans xmlns="http://www.springframework.org/schema/beans"
  3. 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. 4 xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. 5 http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. 6 <!--this is constructor injection-->
  7. 7 <!--the act of creating associations between application components is commonly referred to
  8. 8 as wiring-->
  9. 9 <bean id="knight" class="com.qls.impl.BraveKnight">
  10. 10 <!-- collaborators and configuration for this bean go here -->
  11. 11 <constructor-arg ref="query"></constructor-arg>
  12. 12 </bean>
  13. 13 <bean id="query" class="com.qls.impl.SearchHillQuest">
  14. 14 <constructor-arg value="#{T(System).out}"/>
  15. 15 </bean>
  16. 16 <!-- more bean definitions go here -->
  17. 17 </beans>

//Query接口的代码如下:

  1. 1 package com.qls.inter;
  2. 2
  3. 3 /**
  4. 4 * Created by ${秦林森} on 2017/6/2.
  5. 5 */
  6. 6 public interface Query {
  7. 7 void query();
  8. 8 void embark();
  9. 9 }
  10. 10
  11. 11

//Knight的代码如下:

  1. 1 package com.qls.inter;
  2. 2
  3. 3 /**
  4. 4 * Created by ${秦林森} on 2017/6/2.
  5. 5 */
  6. 6 public interface Knight {
  7. 7 void embarkOnQuest();
  8. 8 }

//Query接口的实现类的代码如下:

//首先是:SlayDragonQuest的代码如下:

  1. 1 package com.qls.impl;
  2. 2
  3. 3 import com.qls.inter.Query;
  4. 4
  5. 5 import java.io.PrintStream;
  6. 6
  7. 7 /**
  8. 8 * Created by ${秦林森} on 2017/6/2.
  9. 9 */
  10. 10 public class SlayDragonQuest implements Query{
  11. 11 private PrintStream stream;
  12. 12
  13. 13 public SlayDragonQuest(PrintStream stream) {
  14. 14 this.stream = stream;
  15. 15 }
  16. 16 @Override
  17. 17 public void embark(){
  18. 18 stream.println("Embarking on quest to slay the dragon");
  19. 19 stream.println("ouyangfeng is the most beautiful woman in the world.");
  20. 20 }
  21. 21 @Override
  22. 22 public void query(){
  23. 23 System.out.println("slay dragon quest");
  24. 24 }
  25. 25 }

//其次是SearchHillQuest的代码如下:

  1. 1 package com.qls.impl;
  2. 2
  3. 3 import com.qls.inter.Query;
  4. 4
  5. 5 import java.io.PrintStream;
  6. 6
  7. 7 /**
  8. 8 * Created by ${秦林森} on 2017/6/3.
  9. 9 */
  10. 10 public class SearchHillQuest implements Query{
  11. 11 private PrintStream stream;
  12. 12
  13. 13 public SearchHillQuest(PrintStream stream) {
  14. 14 this.stream = stream;
  15. 15 }
  16. 16
  17. 17 @Override
  18. 18 public void query() {
  19. 19
  20. 20 }
  21. 21
  22. 22 @Override
  23. 23 public void embark() {
  24. 24 stream.println("the hero search the hill where the damsel was missing");
  25. 25 }
  26. 26 }

//BraveKnight的代码如下:

  1. 1 package com.qls.impl;
  2. 2
  3. 3 import com.qls.inter.Knight;
  4. 4 import com.qls.inter.Query;
  5. 5 import org.springframework.context.annotation.Configuration;
  6. 6
  7. 7 /**
  8. 8 * Created by ${秦林森} on 2017/6/2.
  9. 9 */
  10. 10
  11. 11 public class BraveKnight implements Knight{
  12. 12 private Query query;
  13. 13
  14. 14 public BraveKnight(Query query) {
  15. 15 this.query = query;
  16. 16 }
  17. 17
  18. 18 @Override
  19. 19 public void embarkOnQuest() {
  20. 20 query.embark();
  21. 21 }
  22. 22 }

//测试类的代码如下:

  1. 1 package com.qls.test;
  2. 2
  3. 3 import com.qls.inter.Knight;
  4. 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. 5
  6. 6 /**
  7. 7 * Created by ${秦林森} on 2017/6/2.
  8. 8 */
  9. 9 public class Test {
  10. 10 public static void main(String[] args) {
  11. 11 /**
  12. 12 * 加载配置文件的方式:在src下直接写配置文件的名即可,
  13. 13 * 不直接在src下要把前面的包名加上。包名的前面可加也可以不加斜杠/
  14. 14 */
  15. 15 // ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/com/config/spring-julythird.xml");
  16. 16 // ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/config/spring-julythird.xml");
  17. 17 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-julysecond.xml");
  18. 18 Knight knight = context.getBean(Knight.class);
  19. 19 knight.embarkOnQuest();
  20. 20 context.close();
  21. 21
  22. 22 }
  23. 23 }

一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) set 注入的更多相关文章

  1. spring in action学习笔记一:DI(Dependency Injection)依赖注入之CI(Constructor Injection)构造器注入

    一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) ...

  2. 面试突击77:Spring 依赖注入有几种?各有什么优缺点?

    IoC 和 DI 是 Spring 中最重要的两个概念,其中 IoC(Inversion of Control)为控制反转的思想,而 DI(Dependency Injection)依赖注入为其(Io ...

  3. Spring中依赖注入的四种方式

    在Spring容器中为一个bean配置依赖注入有三种方式: · 使用属性的setter方法注入  这是最常用的方式: · 使用构造器注入: · 使用Filed注入(用于注解方式). 使用属性的sett ...

  4. Spring IOC 依赖注入的两种方式XML和注解

    依赖注入的原理 依赖注入的方式---XML配置 依赖注入的方式---注解的方式 Spring 它的核心就是IOC和AOP.而IOC中实现Bean注入的实现方式之一就是DI(依赖注入). 一 DI的原理 ...

  5. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

  6. Spring注入值得2种方式:属性注入和构造注入

    Spring是一个依赖注入(控制反转)的框架,那么依赖注入(标控制反转)表现在那些地方了? 即:一个类中的属性(其他对象)不再需要手动new或者通过工厂方法进行创建,而是Spring容器在属性被使用的 ...

  7. Spring注解依赖注入的三种方式的优缺点以及优先选择

    当我们在使用依赖注入的时候,通常有三种方式: 1.通过构造器来注入: 2.通过setter方法来注入: 3.通过filed变量来注入: 那么他们有什么区别吗?应该选择哪种方式更好? 三种方式的区别小结 ...

  8. Spring中属性注入的几种方式以及复杂属性的注入

    在Spring框架中,属性的注入我们有多种方式,我们可以通过构造方法注入,可以通过set方法注入,也可以通过p名称空间注入,方式多种多样,对于复杂的数据类型比如对象.数组.List集合.map集合.P ...

  9. Spring 注入的两种方式

    Spring 的两种注入方式: 1. 属性注入:通过无参构造函数+setter方法注入 2. 构造注入:通过有参的构造函数注入. 优缺点: 1. 属性注入直白易懂,缺点是对于属性可选的时候,很多个构造 ...

随机推荐

  1. SIPp常用脚本之三:UAC

    UAC是作为SIP消息的发起端,可以控制消息速率什么的,方便极了. 一.uac.xml <?xml version="1.0" encoding="ISO-8859 ...

  2. JS高级心法——作用域链

    首先我们来看两个js中的代码:    <script type="text/javascript"> var c=5; function t1(){ var d=6 f ...

  3. 使用NuGet发布自己的.NET NuGet 包( .NET Standard & Windows)

    发布自己的nuget包 STEP 1:获取API Key 首先,你需要到NuGet上注册一个新的账号,然后在My Account页面,获取一个API Key,或者是自建服务器上生成一个API Key( ...

  4. unity, shader input and output

    http://wiki.unity3d.com/index.php?title=Shader_Code

  5. 关于K8s集群器日志收集的总结

    本文介绍了kubernetes官方提供的日志收集方法,并介绍了Fluentd日志收集器并与其他产品做了比较.最后介绍了好雨云帮如何对k8s进行改造并使用ZeroMQ以消息的形式将日志传输到统一的日志处 ...

  6. Kafka剖析:Kafka背景及架构介绍

    <Kafka剖析:Kafka背景及架构介绍> <Kafka设计解析:Kafka High Availability(上)> <Kafka设计解析:Kafka High A ...

  7. python2.7 跨文件全局变量的方法

    有关python实现跨文件全局变量的方法. 在使用Python编写的应用的过程中,有时会遇到多个文件之间传递同一个全局变量的情况.文件1:globalvar.py #!/usr/bin/env pyt ...

  8. XILINX之RAM使用指南(加个人总结)

    先加点自己的总结:真双口RAM可以在任意时间访问任意地址,两个端口的地址是一样的,即共享内存和地址.这就会带来一个问题:同时读写一个地址会发生冲突.基于这个点矛盾就要设置限制条件,这个在Xilinx ...

  9. [na]锐起无盘机并发部署多台windows

    小时候很好奇这个技术,也并无卵,只是为了遂儿时愿, 用到锐起无盘部署,支持win7哦: 视频教程: 拓展:网吧电脑为什么没有硬盘? 网吧电脑没有硬盘是怎么运行的? 所需软件: https://yunp ...

  10. flink watermark介绍

    转发请注明原创地址 http://www.cnblogs.com/dongxiao-yang/p/7610412.html 一 概念 watermark是flink为了处理eventTime窗口计算提 ...