文档章节

包办婚姻的Spring IoC

白志华
 白志华
发布于 2015/10/18 10:54
字数 1575
阅读 2
收藏 0
点赞 0
评论 0

基本概念

       IoC(Inversion of Control),直观地讲,就是对象创建或查找对象依赖的控制权由应用代码转到了外部容器,控制权的转移是所谓反转。使用Ioc,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。我们可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它


       IoC还有另外一个名字——“依赖注入DI(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象地说,即由容器动态地将某种依赖关系注入到组件之中。


IoC场景

      上面说的可能有点晕,来一个实际点的例子。


      丽萨已经老大不小了,一直没有男朋友,看着别人恩恩爱爱的,也不禁想找个BoyFriend。摆在她面前的有3种方案:主动“邂逅” Or 同事介绍 Or 父母包办。她会选择哪种呢?

      主动邂逅”方式,如图所示:


public class Girl { 

  public void kiss(){ 
    Boy boy = new Boy(); 
  } 

}
       不过这种美好的纯洁的爱情,一般只会发生在校园里,对于已经是工薪阶层的丽萨显然不太适合。

      第二方案,同事介绍,

public class Girl { 

  void kiss(){ 
    Boy boy = BoyFactory.createBoy(); 
  } 
}

       很多人都是这样找到了自己的另一半。丽萨以前也试着去跟同事介绍的handsome man接触过,但是真人与介绍的出入太大,最起码handsome这条就太符合,而且有他许多缺点。觉得他不适合自己,所以最后也就不了了之。


       所以无奈之下,她的难题丢给了父母。父母给她物色了一个“绝世好男人”——曾小贤(这娃有句经典台词:“好男人就是我,我就是....曾小贤”),终于算是遂了她的心愿了。

public class Girl { 

  void kiss(Boy boy){ 
    // kiss boy 
   boy.kiss(); 
  } 
}

       虽然在现实生活中我们都希望与自己的另一半来场完美的邂逅,但在Spring世界里,跟丽萨一样,选择的却是父母包办,它就是控制反转,而这里具有控制力的父母,就是Spring所谓的容器概念。 


       典型的IoC可以如图所示。

 实例说明IoC注入方式

      IoC有3种注入方式:接口注入、Setter方法注入、构造器注入。由于接口注入不推荐使用,所以只介绍setter方法注入和构造器注入。


       用代码来说明一切吧:

【Girl.java】

package com.tgb;
/**
 * 期待找BF的Girl
 * @author Admin
 *
 */
public class Girl {

	private Boy bf;
	
	
	public Girl(){}
	
	public Girl(Boy bf){
		System.out.print("使用构造方法方式注入:");
		this.bf = bf;
	}
	
	public void setBf(Boy bf) {
		System.out.print("使用Setter方式注入:");
		this.bf = bf;
	}

	public void kissYourBF() {
		bf.kiss();
	}
}
【Boy.java】
package com.tgb;

/**
 * 合格的BF
 * @author Admin
 *
 */
public class Boy {

	public void kiss(){
		System.out.println("My boy friend,I'll kiss you!");
	}
}
【Client客户端】
package com.tgb;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {

	public static void main(String[] agrs){
		ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Girl lisa = (Girl)factory.getBean("girl");
		lisa.kissYourBF();
		
	}
}
【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"
	     xmlns:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

	<bean id="boy" class="com.tgb.Boy" />
	<bean id="girl" class="com.tgb.Girl">
		<!--构造器注入-->
		<constructor-arg ref="boy"></constructor-arg>
		<!--Setter方法注入-->
		<!--<property name="bf" ref="boy"></property>-->
	</bean>
</beans>

       选择Setter方法注入和 构造器注入的控制是在配置文件中完成的。结果如下:




      Setter方法注入时,有2种装载方式需要注意,byName和byType。当我在配置文件中,把2种注入方式都注释掉,同时添加了default-autowire="byType",

<?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:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
           default-autowire="byType"
           >

	<bean id="boy" class="com.tgb.Boy" />
	<bean id="girl" class="com.tgb.Girl">
		<!--构造器注入-->
		<!--<constructor-arg ref="boy"></constructor-arg>-->
		<!--Setter方法注入-->
		<!--<property name="bf" ref="boy"></property>-->
	</bean>
</beans>

       执行结果如图



       但是换成default-autowire="byName",则会报如下错误:


       这是为什么呢?原因在于,当使用byType方式装载时,Spring是根据classType来确定要实例化的类。所以就算bean的id是boy,跟Girl中bf的Setter名字不一致,依旧可以实例化。但是使用byName时,则是根据id来实例化类的。所以只要把Boy类对应的bean id跟Girl中的setter方法名一致才行,即修改id="boy"为id="bf",即可正常显示:

<bean id="bf" class="com.tgb.Boy" />
	<bean id="girl" class="com.tgb.Girl">
		<!--构造器注入-->
		<!--<constructor-arg ref="boy"></constructor-arg>-->
		<!--Setter方法注入-->
		<!--<property name="bf" ref="boy"></property>-->
	</bean>

       另一种修改方式就是用显示的方式来设定Setter方法所注入的是哪个类的对象:

<bean id="boy" class="com.tgb.Boy" />
	<bean id="girl" class="com.tgb.Girl">
		<!--构造器注入-->
		<!--<constructor-arg ref="boy"></constructor-arg>-->
		<!--Setter方法注入-->
		<property name="bf" ref="boy"></property>
	</bean>
       执行结果如图:


2种注入方式的比较

       Setter 注入:

    • 对于习惯了传统 javabean 开发的程序员,通过 setter 方法设定依赖关系更加直观。
    • 如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。
    • 如果用到了第三方类库,可能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。

       构造器注入:

    • 在构造期间完成一个完整的、合法的对象。
    • 所有依赖关系在构造函数中集中呈现。
    • 依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。
    • 只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。


版权声明:本文为博主原创文章,未经博主允许不得转载。

本文转载自:http://blog.csdn.net/xiaoxian8023/article/details/17148931

共有 人打赏支持
白志华
粉丝 29
博文 265
码字总数 57524
作品 0
长沙
程序员
在spring中如何配置和使用一个Bean

在Spring中,那些组成你应用程序的主体(backbone)及由Spring IoC容器所管理的对象,被称之为bean。 简单地讲,bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中...

冰雷卡尔
2012/07/24
0
0
深入理解Spring源码(一)-IOC容器的定位,载入,注册

前言:Spring源码继承,嵌套层次非常多,读起来非常容易晕,小伙伴们在看文章的时候一定要跟着文章的思路自己去源码里点一点,看一看,并且多看几次。就会越来越清晰。下面开始正题 1.Spring...

Meet相识_bfa5
05/01
0
0
Spring IoC(更新中)

概念 IoC(控制反转,也叫依赖注入DI)是Spring的核心,几乎Spring的所有组件都要建立在此基础之上,包括AOP,声明式事务,SpringMVC等等。那么IoC的主要目的是什么呢?两个字“解耦”。为什么...

互联网小龙虾
2014/03/04
0
0
1 Spring核心:IoC容器的实现

依赖控制反转的实现有很多种方式。在Spring中,IoC容器是实现这个模式的载体, 它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方...

qq_18150351
04/24
0
0
Spring中ApplicationContext和beanfactory区别

org.springframework.beans及org.springframework.context包是Spring IoC容器的基础。BeanFactory提供的高级配置机制,使得管理任何性质的对象成为可能。ApplicationContext是BeanFactory的扩...

ArlenXu
2015/01/18
0
0
spring中的AOP与IOC

在J2EE的整个发展历程中,现在正是一个非常时刻。从很多方面来说,J2EE都是一个伟大的成功:它成功地在从前没有标准的地方建立了标准;大大提升了企业级软件的开放程度,并且得到了整个行业和...

Sandy_wu
2013/06/08
0
0
Spring IoC & DI

IOC诞生的历史 在没有IoC时,关联不同模块是通过类实例实现的,代码可能是这样子的: 当YourServiceImpl的接口不变时,只需要根据业务需要更换不同的YourService实现类即可。一旦更换实现类时...

classfly
06/18
0
0
Spring集成 Struts2

Spring如何整合struts2? 1) 整合目标? 使IOC容器来管理Struts2的Action! 2) 如何进行整合? ① 正常加入Struts2 ② 在Spring的IOC容器中配置Struts2的Action 特别注意:在IOC容器中配置S...

哎小艾
2017/11/08
0
0
SpringBoot的幕后推手...

一、背景   这两年随着微服务的盛行,SpringBoot框架水到渠成的得到了高曝光,作为程序猿的我们,现在要是不知道一点SpringBoot相关的东西,貌似出去找工作都会被深深地鄙视,不过在我们开...

Java工程师-Distance
06/01
0
0
Spring 源码解读 推荐流程

Spring源代码解析(一):IOC容器:http://www.javaeye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.javaeye.com/topic/86594 Spring源代码解析(三):Sprin...

2k10
2015/04/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

about git flow

  昨天元芳做了git分支管理规范的分享,为了拓展大家关于git分支的认知,这里我特意再分享这两个关于git flow的链接,大家可以看一下。 Git 工作流程 Git分支管理策略   git flow本质上是...

qwfys
今天
2
0
Linux系统日志文件

/var/log/messages linux系统总日志 /etc/logrotate.conf 日志切割配置文件 参考https://my.oschina.net/u/2000675/blog/908189 dmesg命令 dmesg’命令显示linux内核的环形缓冲区信息,我们可...

chencheng-linux
今天
1
0
MacOS下给树莓派安装Raspbian系统

下载镜像 前往 树莓派官网 下载镜像。 点击 最新版Raspbian 下载最新版镜像。 下载后请,通过 访达 双击解压,或通过 unzip 命令解压。 检查下载的文件 ls -lh -rw-r--r-- 1 dingdayu s...

dingdayu
今天
1
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
今天
2
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
今天
1
0
Java工具类—随机数

Java中常用的生成随机数有Math.random()方法及java.util.Random类.但他们生成的随机数都是伪随机的. Math.radom()方法 在jdk1.8的Math类中可以看到,Math.random()方法实际上就是调用Random类...

PrivateO2
今天
3
0
关于java内存模型、并发编程的好文

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在...

DannyCoder
昨天
1
0
dubbo @Reference retries 重试次数 一个坑

在代码一中设置 成retries=0,也就是调用超时不用重试,结果DEBUG的时候总是重试,不是0吗,0就不用重试啊。为什么还是调用了多次呢? 结果在网上看到 这篇文章才明白 https://www.cnblogs....

奋斗的小牛
昨天
2
0
数据结构与算法3

要抓紧喽~~~~~~~放羊的孩纸回来喽 LowArray类和LowArrayApp类 程序将一个普通的Java数组封装在LowArray类中。类中的数组隐藏了起来,它是私有的,所以只有类自己的方法才能访问他。 LowArray...

沉迷于编程的小菜菜
昨天
1
0
spring boot应用测试框架介绍

一、spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit、spring test、assertj、hamcrest、mockito、jsonassert、jsonpath),但是在数...

yangjianzhou
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部