Spring是一个轻量级的Java开发框架,其提供的两大基础功能为IoC和AOP,其中IoC为依赖反转(Inversion of Control)。IOC容器的基本理念就是“为别人服务”,那为别人服务什么呢?其中最重要就是业务对象的构建管理和业务对象之间的依赖绑定。

  • 业务对象的构建管理:业务场景中,无需关心业务对象如何创建、如何管理,在需要时只需获取即可。业务对象的构建管理交给IoC容器,避免这部分代码对业务逻辑的侵染。
  • 业务对象之间的依赖绑定:IoC容器需要先了解业务对象之间的依赖关系,这样依据之前业务对象的构建管理就可以对外提供IoC服务,保证每个业务对象在使用时处于就绪状态。

IoC容器管理业务对象,首先需要知道业务对象之间的依赖关系,以下有几种方式告诉IoC容器其管理的对象之间的绑定关系:

  • 可以通过简单的文本方式记录被注入对象和其依赖对象的对应关系。
  • 使用描述性更强的XML文件格式记录对象之间的对应关系。
  • 还可以通过编写代码的方式(调用IoC容器提供的对应API)设置对象之间的关系。
  • ...

注意:不管是什么方式来告知IoC容器对象之间的绑定关系,最终都是需要通过编码方式来将这些信息"写入"到IoC容器中的。

一个XML配置方式的示例:

<!-- 配置bean,属性配置方式 -->
<bean id="helloWorld" class="com.luo.testspring.HelloWorld" scope="singleton">
<property name="name" value="spring"/>
</bean>

Spring的IoC容器提供两种基本的容器类型:BeanFactory和ApplicationContext。

  • BeanFactory:基础类型IoC容器,提供基本的容器服务,如果没有特殊指定,采用延迟初始化策略,也就是当客户端需要容器中某个对象时,才对该受管理的对象初始化及其依赖注入操作。所以,相对来说,BeanFactory容器启动较快,所需资源有限,对于资源有限,并且功能要求不严格的场景,使用BeanFactory容器是比较合适的。
  • ApplicationContext:ApplicationContext是在BeanFactory基础之上构建的,是一个比较高级的容器,除了拥有BeanFactory的全部功能外,也提供其他高级特性,比如事件发布、国际化信息支持等。ApplicationContext所管理的对象,默认ApplicationContext启动之后全部初始化并绑定完成,所以其启动较慢,占用资源较多。在系统资源充足,并需要提供较多功能的使用场景,ApplicationContext是一个不错的选择。

BeanFactory使用示例(XML配置方式):

/* HelloWolrd类,待依赖注入的类 */
public class HelloWorld {
private String name; public HelloWorld() {
} public HelloWorld(String name) {
this.name = name;
} public void setName(String name) {
this.name = name;
} public void hello() {
System.out.println("hello: " + this.name);
}
}
<!-- springConfig.xml配置文件Bean配置 -->

<!-- 配置bean,属性配置方式 -->
<bean id="helloWorld" class="com.luo.testspring.HelloWorld" scope="singleton">
<property name="name" value="spring"/>
</bean> <!-- 通过构造方法配置bean属性 -->
<bean id="helloWorld2" class="com.luo.testspring.HelloWorld">
<constructor-arg value="spring2" index="0"></constructor-arg>
</bean> <bean id="helloWorld3" class="com.luo.testspring.HelloWorld">
<property name="name">
<bean class="java.lang.String">
<constructor-arg value="spring3"/>
</bean>
</property>
</bean>
/* 测试代码 */
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("springConfig.xml")); HelloWorld helloWorld = (HelloWorld) factory.getBean("helloWorld");
helloWorld.hello(); HelloWorld helloWorld2 = factory.getBean("helloWorld2", HelloWorld.class);
helloWorld2.hello(); HelloWorld helloWorld3 = factory.getBean("helloWorld3", HelloWorld.class);
helloWorld3.hello();

ApplicationContext使用示例(XML配置方式):

/* 测试代码 */
HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
helloWorld.hello(); HelloWorld helloWorld2 = ctx.getBean("helloWorld", HelloWorld.class);
helloWorld2.hello(); HelloWorld helloWorld3 = ctx.getBean("helloWorld3", HelloWorld.class);
helloWorld3.hello();

依赖注入的3种方式

  • 构造方法注入:调用被注入对象的构造方然注入,优点是对象在构造完成就进入了就绪状态。
  • 属性注入:调用被注入对象的setter/getter方法。
  • 接口注入:现在不提倡的一种方式,因为它强制被注入对象实现不必要的接口,带有侵入性。

spring的bean配置(XML配置方式)

属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象,使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值,属性注入是实际应用中最常用的注入方式。属性注入Bean类须有一个默认的构造方法。

<!-- Hello类中有一个String类型的msg属性 -->
<bean id="hello" class="com.luoxn28.Hello">
<property name="msg" value="luoxn28"/>
</bean>

通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用,构造器注入在 <constructor-arg> 元素里声明属性。

<bean id="msg" class="java.lang.String">
<constructor-arg value="string"/>
</bean>
<!-- 按照索引匹配入参 -->
<bean id="car" class="com.luoxn28.Car">
<constructor-arg value="比亚迪" index="0"/>
<constructor-arg value="中国制造" index="1"/>
<constructor-arg value="200000" index="2"/>
</bean>
<!-- 按照类型匹配入参 -->
<bean id="car2" class="com.luoxn28.Car">
<constructor-arg value="比亚迪" type="java.lang.String">
<constructor-arg value="中国制造" type="java.lang.String"/>
<constructor-arg value="200000" type="double"/>
</bean>

组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能。要使 Bean 能够相互访问,就必须在 Bean 配置文件中指定对 Bean 的引用,在 Bean 的配置文件中,可以通过 <ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用。也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean。

<bean id="msg" class="java.lang.String">
<constructor-arg value="luoxn28"/>
</bean> <!-- Hello类中有一个String类型的msg属性 -->
<bean id="hello" class="com.luoxn28.Hello">
<property name="msg" ref="msg"/>
</bean>

当 Bean 实例仅仅给一个特定的属性使用时,可以将其声明为内部 Bean,内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里,不需要设置任何 id 或 name 属性。内部 Bean 不能使用在任何其他地方。

<!-- Hello类中有一个String类型的msg属性 -->
<bean id="hello" class="com.luoxn28.Hello">
<property name="msg">
<bean class="java.lang.String">
<constructor-arg value="luoxn28"/>
</bean>
</property>
</bean>

可以通过一组内置的 xml 标签(例如: <list>, <set> 或 <map>) 来配置集合属性。

<!-- CollectionClass类有3个属性,List<String> list、Set<String> set、Map<String, String> map-->
<bean id="collectionClass" class="com.luoxn28.CollectionClass">
<property name="list">
<list>
<value>luoxn28</value>
<value>luoxn29</value>
<value>luoxn30</value>
</list>
</property>
<property name="set">
<set>
<value>luoxn28</value>
<value>luoxn29</value>
<value>luoxn30</value>
</set>
</property>
<property name="map">
<map>
<entry key="str1" value="luoxn28"/>
<entry key="str2"><value>luoxn29</value></entry>
<entry key="str3"><value>luoxn30</value></entry>
</map>
</property>
</bean>

Bean的作用域

Spring最初提供两种bean的scope类型:singleton和prototype,在发布2.0之后,新增了request、session和global session类型,不过这3种新增的只能用在Web应用中。可以通过bean属性scope来指定bean的scope类型,如果是singleton类型的话,在用户获取该bean之后,容器还是会接管该bean的生命周期;如果是prototype的话,在用户获取该bean之后,容器就不接管该bean了,也就是容器每次会创建一个新的bean对象返回给用户。

<!-- Hello对象每次获取都会新建 -->
<bean id="hello" class="com.luoxn28.Hello" scope="prototype">
<property name="msg" value="luoxn28"/>
</bean>

通过静态方法创建bean

调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中,当用户需要对象时,只需要简单地调用静态方法,而不同关心创建对象的细节。要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 <constrctor-arg> 元素为该方法传递方法参数。

public static Hello createHello() {
return new Hello();
}
<bean id="hello" class="com.luoxn28.Hello" factory-method="createHello">
</bean>

通过实例方法创建bean

将对象的创建过程封装到另外一个对象实例的方法里. 当用户需要请求对象时, 只需要简单的调用该实例方法而不需要关心对象的创建细节。要声明通过实例工厂方法创建的 Bean,在 bean 的 factory-bean 属性里指定拥有该工厂方法的 Bean,在 factory-method 属性里指定该工厂方法的名称,使用 construtor-arg 元素为工厂方法传递方法参数。

Spring的IoC容器的更多相关文章

  1. Spring框架IOC容器和AOP解析

    主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置  一.S ...

  2. Spring之IOC容器加载初始化的方式

    引言 我们知道IOC容器时Spring的核心,可是如果我们要依赖IOC容器对我们的Bean进行管理,那么我们就需要告诉IOC容易他需要管理哪些Bean而且这些Bean有什么要求,这些工作就是通过通过配 ...

  3. spring框架--IOC容器,依赖注入

    思考: 1. 对象创建创建能否写死? 2. 对象创建细节 对象数量 action  多个   [维护成员变量] service 一个   [不需要维护公共变量] dao     一个   [不需要维护 ...

  4. 在Servlet(或者Filter,或者Listener)中使用spring的IOC容器

    web.xml中的加载顺序为:listener > filter > servlet > spring. 其中filter的执行顺序是filter-mapping在web.xml中出 ...

  5. Spring的IOC容器第一辑

    一.Spring的IOC容器概述 Spring的IOC的过程也被称为依赖注入(DI),那么对象可以通过构造函数参数,工厂方法的参数或在工厂方法构造或返回的对象实例上设置的属性来定义它们的依赖关系,然后 ...

  6. SpringMVC系列(十五)Spring MVC与Spring整合时实例被创建两次的解决方案以及Spring 的 IOC 容器和 SpringMVC 的 IOC 容器的关系

    一.Spring MVC与Spring整合时实例被创建两次的解决方案 1.问题产生的原因 Spring MVC的配置文件和Spring的配置文件里面都使用了扫描注解<context:compon ...

  7. spring的Ioc容器与AOP机制

    为什么要使用Spring的Ioc容器? 1.首先,spring是一个框架,框架存在的目的就是给我们的编程提供简洁的接口,可以使得我们专注于业务的开发,模块化,代码简洁,修改方便. 通过使用spring ...

  8. Spring扩展:Spring的IoC容器(注入对象的方式和编码方式)

    二.Spring的IoC容器 IoC:Inversion of Control(控制反转) DI:Dependency Injection(依赖注入) 三.依赖注入的方式 (1)构造注入 (2)set ...

  9. spring之IOC容器创建对象

    1.术语了解 1.1组件/框架设计 侵入式设计 引入了框架,对现有的类的结构有影响:即需要实现或继承某些特定类. 例如: Struts框架非侵入式设计 引入了框架,对现有的类结构没有影响. 例如:Hi ...

随机推荐

  1. Linux系统(三)系统基础扫盲大全

    序言 如果大家都爱装逼,一般会偏爱使用安装最小化的liunx系统,那么你的系统就不带图形化的桌面功能,这样对于一个想装B的初学者来说,Liunx就是黑漆马虎,一望无际的黑屏,黑屏,如何快速的对liun ...

  2. 修改本地配置远程连接oracle数据库

    当我们需要查看数据库信息时,我们更愿意通过客户端来查看,这样不仅操作方便,而且查看更精准.那么需要远程连接数据库需要在本地修改那些配置呢?以下是我个人的经验,希望大家都指正. 1.在oracle安装目 ...

  3. Lua与.net的CLR相互调用

    工程环境搭建: 下载luainterface-1.5.3.zip文件,使用到的dll为Built目录下的LuaInterface.dll.lua51.dll.luanet.dll LuaInterfa ...

  4. Codeforce 水题报告(2)

    又水了一发Codeforce ,这次继续发发题解顺便给自己PKUSC攒攒人品吧 CodeForces 438C:The Child and Polygon: 描述:给出一个多边形,求三角剖分的方案数( ...

  5. JAVA对特殊的字符串进行html编码

    SourceURL:about:blank /** * Created by Administrator on 2016/9/22. */public class HtmlEncode { publi ...

  6. 浅谈Jasmine的安装和拆卸

    单元测试中,我们通常需要在执行测试代码前准备一些测试数据,建立测试场景,这些为了测试成功而所做的准备工作称为Test Fixture.而测试完毕后也需要释放运行测试所需的资源.这些铺垫工作占据的代码可 ...

  7. 把时间还给洞察,且看PPT调研报告自动生成攻略

    文/JSong @2017.02.28 在数据分析里面有一句话是说,80%的时间要用于数据清洗和整理,而我觉得理想的状态应该是把更多的把时间花在数据背后的洞察当中.去年11月在简书占了个坑,说要自己写 ...

  8. 使用JS实现手风琴效果

    想要实现简单的手风琴切换效果,需要使用JS实现,如下是使用javascript源码实现,后续会更新使用jQuery实现. 1. 先进行简单的布局:我们可以再ul下添加几个li实现html的简单布局,再 ...

  9. nginx新手入门

    nginx的应用 官网(nginx.org) nginx可以做1.web服务(http服务)2.http代理服务3负载均衡在官网(nginx.org)如下图处下载先点击 跳转下一页点击(nginx/w ...

  10. Androidstudio项目分享到Git@OSC托管

    Androidstudio项目分享到Git@OSC托管. 一.在OSC创建仓库 例如,创建一个AndroidStudy仓库,创建步骤如下: 输入仓库名称 点击创建按钮,就可以完成仓库的创建,如下图所示 ...