控制反转容器(IoC Container)是Spring的一个重要基础功能,不喜欢新名词的同窗,姑且理解为组件装配容器.java
要理解Spring的设计精神,先来看看Spring的设计初衷.git
先看看没有Spring以前,咱们怎么作.
以一个现实的状况说明.你们应该都有过购买手机的经历.
收到手机后,打开包装, 给手机装上SIM卡,装上电池,开机 ... github
咱们用java面向对象的思想作设计:
手机,SIM卡,电池, 这是三个对象,也可称为实体,物体,组件,零件
名称不重要,反正这是三个东西,天然对应三个java 对象.
1, Battery.javaspring
package demo; public class Battery{ private String power; public Battery(String power){ this.power = power; } public String getPower(){ return this.power; } }
2, Simcard.javawindows
package demo; public class Simcard{ private String number; public Simcard(String number){ this.number = number; } public String getNumber(){ return this.number; } }
3, Mobile.java数组
package demo; public class Mobile{ private String brand; private Battery battery; private Simcard simcard; public Mobile(String brand){ this.brand = brand; } public void setBattery(Battery battery){ this.battery = battery; } public void setSimcard(Simcard simcard){ this.simcard = simcard; } public void poweron(){ System.out.println("Mobile: " + this.brand + " powered on"); System.out.println("Battery: " + this.battery.getPower() ); System.out.println("Simcard: " + this.simcard.getNumber() ); } }
4, 运行程序 Main.javagradle
package demo; public class Main{ public static void main(String[] args) { //建立零件 Mobile mobile = new Mobile("XiaoMI1"); Battery battery = new Battery("2000mA"); Simcard simcard = new Simcard("13612345678"); //组装零件 mobile.setBattery(battery); mobile.setSimcard(simcard); //使用 mobile.poweron(); } }
以上程序不使用Spring,运行良好.
由于这里只有三个零件,建立和组装都没有问题.
若有一个设备由1000个零件,建立和组装过程就很繁琐.
试想,咱们网购了一辆山地自行车,要把它装配起来,咱们首先会看货品清单和装配说明书.this
Spring 容器就是为建立和组装零件而设计的.设计
在介绍Spring 容器以前, 先介绍一下容器的概念,初学者会对容器概念感到陌生.
现实生活中,装有糖果的盒子就是容器,Java里的容器和现实生活相似,只不过装的是对象实例.
这里对 Main.java 作些修改以解释容器概念
4, 运行程序 Main.javacode
package demo; public class Main{ public static void main(String[] args) { //建立容器 Object[] container = new Object[3]; //建立和组装实例 Mobile mob = new Mobile("XiaoMI1"); Battery bat = new Battery("2000mA"); Simcard sim = new Simcard("13612345678"); mob.setBattery(bat); mob.setSimcard(sim); //放入容器 container[0] = mob; container[1] = bat; container[2] = sim; //从容器中获取实例 Mobile mobile = (Mobile) container[0]; mobile.poweron(); } }
以上程序建立数组做为容器, 建立和组装实例后放入容器, 使用时,从容器中获取实例.
这个程序看起来有些画蛇添足,确体现了容器的主要特性.
这里,咱们手动完成了 建立容器->建立和组装实例->放入容器的工做.
使用Spring后,这些工做就能够由Spring来完成.
这里,咱们使用对象数组做为容器, 经过数字下标获取对象, Spring 使用ConcurrentHashMap 做为容器, 经过字符串ID获取对象. (事实上ConcurrentHashMap 内部也是把对象包装一下放到数组里)
这里,零件之间的装配关系经过人工完成,而Spring经过配置文件来描述零件之间的装配关系.
Spring的配置文件使用XML格式描述组件清单和装配关系,这个配置文件至关于现实生活中的货品清单和装配说明书.
使用Spring容器时,须要一个配置文件(货品清单) manifest.xml
5, manifest.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-4.0.xsd"> <bean id="battery1" class="demo.Battery"> <constructor-arg name="power" value="3000mA" /> </bean> <bean id="simcard1" class="demo.Simcard"> <constructor-arg name="number" value="13512345678" /> </bean> <bean id="mobile1" class="demo.Mobile"> <constructor-arg name="brand" value="Xiaomi" /> <property name="Simcard" ref="simcard1"/> <property name="Battery" ref="battery1"/> </bean> </beans>
这里的bean 就是对象实例的意思,java里全部对象实例均可称为bean
这个配置文件,简单的说就是一个bean的列表. 每一个bean经过XML配置其建立初始值或是装配对象. id属性,是为了之后便于从容器中获取.
这个配置文件里battery1,simcard1 咱们设定的构造参数,而mobile1, 咱们设定了构造参数的同时还装配了具体的Battery和Simcard.
4, 运行程序 Main.java( 使用Spring)
package demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main{ public static void main(String[] args) { ApplicationContext context= new ClassPathXmlApplicationContext("manifest.xml"); Mobile mobile = (Mobile) context.getBean("mobile1"); System.out.println("************************"); mobile.poweron(); } }
这里的context, 简单的理解就是对象容器, Spring 经过分析配置文件完成对象建立,装配的工做.
使用时,经过ID获取容器对象.
Spring容器经过配置文件来描述零件清单和装配关系,装配关系变更时,修改配置便可,不用从新编译代码.
对于简单的例子,看不出Spring容器的优点.
当对于零件不少,装配关系复杂多变的系统,就能体现Spring的优点.
Spring 容器除了使用xml来配置,还可使用注解(annotation)来配置. 注解配置,这里不在展开细说,总之,二者的功能是同样的,看我的喜爱使用.
运行源代码
git clone https://github.com/huanghq/SpringContainerExample.git
cd SpringContainerExample/
./gradlew run
(windows 用户:gradlew.bat run)
************************ Mobile: Xiaomi powered on Battery: 3000mA Simcard: 13512345678
运行源代码要求Java1.7 环境,支持跨平台.
使用gradle 下载依赖包,编译运行.不熟悉gradle的同窗不要紧.
只需专一上述java文件和配置文件,
第一次运行须要下载gradle和java依赖包,有些慢,耐心等待.
对控制反转(IOC)概念感兴趣的同窗,参看下文:
Java开发中的依赖注入(DI)和控制反转(IOC)