在分析原理之前我们先回顾下依赖注入的概念:

我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。

其实简单的说,依赖注入起到的作用就是讲对象之间的依赖关系从原先的代码中解耦出来,通过配置文件或注解等方式加上Spring框架的处理让我们对依赖关系灵活集中的进行管理。  

下面谈谈Spring是如何实现反转模式IOC或依赖注入模式DI:

平时,我们需要生成一个对象,使用new语法,如一个类为A

public class A{
public void myMethod(){
System.out.println("hello");
}
}

如果我们在 B中调用A,那么如下代码:

public class B{
public void invoke(){
A a = new A();
a.myMethod();
}
}

每次执行invoke方法时,都要生成一个A对象,如果A对象代码较长,这是费时的事
情。于是有如下写法:

public class B{
A a = new A();
public void invoke(){
a.myMethod();
}
}

将A对象变成B的类属性。 如果我们不想在B中实现A的实例,也就是不想立即new A(),而是想通过外界传入, 注意,如果你想知道为什么,这里涉及到设计模式以及解耦等因素,进一步感兴趣者可学习 本站的GoF 23 种设计模式。

如果想让A的实例从外界传入,有两种写法:

public class B{
A a;
public void setA(A a){
this.a = a;
}
public A getA(){
return a;
}
public void invoke(){
a.myMethod();
}
}

这种写法,A并没有被实例化,需要通过外界调用setA方法,将A的对象实例赋入B中. 或者通过B的构造函数传入,如下:

public class B{
A a;
public B(A a){
this.a = a;
}
public void invoke(){
a.myMethod();
}
}

上述两种写法在编程中是经常发生的,B作为调用者,A是被调用者,A的实例化不在 调用者B内部中完成,而是通过构造函数或setXXX方法赋值进来,这种方式我们称为依赖 性注射(IoC 模式),B 和A 的依赖联系是通过构造函数或setXXX 方法赋值进来,这样, 最大程度解耦了调用者B和被调用者A之间的耦合联系。

Spring如何实现依赖注射?

上文提到:A的实例化不在调用者B内部中完成,而是通过构造函数或setXXX 方法赋 值进来,Spring实际就是完成这个赋值的过程。 为了让Spring自动完成B代码中的A的实例化,需要通过配置文件告诉Spring有关A 的类的属性,这个配置是applicationContext.xml文件。 在 applicationContext.xml中,我们先定义JavaBeans为B的配置:

<beans>
<bean id="b" class="springsimple.B"/>
</beans>

这是最常用的JavaBeans的定义,id相当于对象名,当前文件应该是唯一。后来Spring使用@Component替代。

再在applicationContext.xml定义A的配置如下:

<beans>
<bean id="b" class="springsimple.B"/>
<bean id="a" class="springsimple.A"/>
</beans>

这样我们告诉Spring我们有两个JavaBeans,现在解决关键问题,B代码中还调用了A, 那么如何让Spring将A的实例注射到B中?使用Spring配置的property语法。具体配置如 下:

<beans>
<bean id="b" class="springsimple.B">
<property name="a"><ref local="a" /></property> <!— 增加这一行-->
</bean>
<bean id="a" class="springsimple.A" />
</beans>

增加一行说明:B 的属性a 指向了a,这样,Spring 会知道B 中属性a 的实例就是 springsimple.A,在B实例化时将会将B中的a 实现实例化,这是通过setA方法注射进入。 注意,property name="a"中的a 是setA字符中去掉set 后的字符串,这个字符串第一个 必须是小写,例如,如果B中有setOneA方法,那么,配置文件应该是property name="oneA"。

在Spring Boot以后版本已经可以使用@Autowire进行自动匹配,无需如此繁琐配置了。

参考:

Spring依赖注入原理分析的更多相关文章

  1. Spring学习笔记——Spring依赖注入原理分析

    我们知道Spring的依赖注入有四种方式,各自是get/set方法注入.构造器注入.静态工厂方法注入.实例工厂方法注入 以下我们先分析下这几种注入方式 1.get/set方法注入 public cla ...

  2. Spring 依赖注入原理

    所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bean对象,以及销毁它.所以我们只需从容器直接获取Bean对象就行, ...

  3. Spring依赖注入原理

    接触过spring 的同学应该都知道依赖注入,依赖注入又称控制反转,其内涵就是,将创建某个bean的控制权力,由原来需要引用这个bean的bean转移(反转)到外部的spring IOC容器,由IOC ...

  4. 形象化的spring 依赖注入原理

      转. IoC就是Inversion of Control,控制反转.在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制.这称为控制反转. 下面我们以几个例子来说明什 ...

  5. spring依赖注入原理剖析

    PropertyDefinition.java package junit.test; public class PropertyDefinition { private String name; p ...

  6. Spring 依赖注入优化

    Spring 依赖注入优化 原创: carl.zhao SpringForAll社区 今天 Spring 最大的好处就是依赖注入,关于什么是依赖注入,在Stack Overflow上面有一个问题,如何 ...

  7. Spring 源码分析之 bean 依赖注入原理(注入属性)

         最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...

  8. Spring、Spring依赖注入与编码剖析Spring依赖注入的原理

    Spring依赖注入 新建PersonIDao 和PersonDao底实现Save方法: public interface PersonIDao { public void save(); } pub ...

  9. (转)编码剖析Spring依赖注入的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...

随机推荐

  1. 建立window SVN服务器

    在windows下搭建SVN服务器: 首先从http://www.visualsvn.com/server/download/ 下载最新的VisualSVN-Server-x.x.x.msi,然后本机 ...

  2. 【Unity笔记】提示框ToolTips大小自适应,及其闪烁的问题

    需求:制作了一个提示框,当鼠标移入背包格子内,显示提示框,且提示框位置跟随鼠标移动.当鼠标移出背包格子,隐藏提示框. 制作提示框ToolTips 因为提示框的大小要求随着显示的文本内容长度而自动大小适 ...

  3. mysql 分区处理数据

    记录一下分区代码: 1.建立存储过程,将原表按照时间转化为分区表,并建立当天分区 #alter table to partition table DELIMITER $$ USE `dc_log`$$ ...

  4. spring 加载jar包中的配置文件

    package com.xxx.ssptsppt.dataexchange.utils; import com.xxx.maybee.engine.utils.FileUtil; import com ...

  5. <context annotation-config />标签意义

    该标签隐式的向Spring容器注册了: AutowiredAnnotationBeanPostProcessor CommondAnnotationBeanPostProcessor Persiste ...

  6. 关于GO语言遇到illegal UTF-8 encoding 随手记录

    在使用汉字的时候会报错 解决方案 editpad++ 修改编码为UTF-8 保存就可以了~bingo

  7. 两个有序单链表合并成一个有序单链表的java实现

    仅作为备注, 便于自己回顾. import java.util.Arrays; public class MergeSort { public static class LinkedNode<V ...

  8. Linux之查看切换Shell

    1.查看存在的shell cat /etc/shells 2.查看使用的shell echo $SHELL 3.切换shell 切换bash chsh -s /bin/bash 切换zsh chsh ...

  9. java service domain dao 分层思路

    今天在开发项目的时候,对项目的java后台的分层有一些看法: 首先,鼓励使用service domain dao 层分层设计概念. 其次,对几层作用的理解: 第一:dao层操作单表,不涉及复杂逻辑,主 ...

  10. Android hide Navigation bar

    最近一个app需要隐藏Navigation bar导航栏. 参考文档 http://blog.csdn.net/zwlove5280/article/details/52823128 http://j ...