Spring4 IOC详解

上一章对Spring做一个快速入门的教程,其中只是简单的提到了IOC的特性。本章便对Spring的IOC进行一个详解。主要从三个方面开始:基于xml文件的Bean配置,基于注解的Bean配置和IOC容器Bean的生命周期。


基于xml文件的Bean配置

首先是applicationContext.xml文件,这可是核心文件。

配置一个bean,需要一个id去唯一标识它,用class指定Bean对象的路径,作用域默认是单例。

通过prototype进行属性赋值,name是属性名,value是值,也可以用ref引用对象,用list,map设置集合。

用SpEL表达式语言赋值,用p命名空间简化赋值,用继承和依赖简化代码。

<?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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置一个 bean
bean中有一个id,且id是唯一的。若不指名则为该类的类名并首字母小写。
property 中有一个name,其name就是生产了setter方法的属性,value便是其值。
-->
<!-- Bean 的作用域
singleton:单例,默认值,容器初始化创建bean实例,在整个生命周期内只创建一个bean。
prototype:原型,容器初始化不创建bean实例,每次请求的时候会创建一个新的bean
-->
<bean id="entity" class="com.itdragon.spring.my.Entity" scope="prototype">
<!-- 属性赋值
属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
-->
<property name="intValue" value="1"></property>
<!-- 引用bean
细节:
1. 用ref 是引用外部bean
2. 也可以直接写在当前bean里面,这就是内部bean, 内部bean是不能被外部引用
-->
<property name="spELEntity" ref="spELEntity"></property>
<!-- 构造器注入
构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性,按照构造器参数顺序赋值
细节:
1. 也可以用index(按索引匹配入参),和type(按类型匹配入参)去指定赋值。实际上是没有必要的
2. 使用构造器注入的前提是 entity 被初始化。
3. 特殊字符,需要用 <![CDATA[内容]]> 这属于xml语法
-->
<constructor-arg value="1.1" />
<constructor-arg >
<value><![CDATA[<ITDragon>]]></value>
</constructor-arg>
<property name="listValue">
<list>
<value>欢迎阅读</value>
<value>ITDragon</value>
<value>的博客!</value>
</list>
</property>
<property name="mapValue">
<map>
<entry key="one" value="1"></entry>
<entry key="two" value="2"></entry>
</map>
</property>
</bean> <!-- SpEL 表达式语言, #{…} 作为定界符, 操作和java相似-->
<bean id="spELEntity" class="com.itdragon.spring.my.SpELEntity">
<property name="intSpel" value="#{1}"></property>
<property name="floatSpel" value="#{entity.intValue + 0.2}"></property>
<property name="stringSpel" value="#{'Spring4基础教程'}"></property>
<property name="bSpel" value="#{2 >= 1}"></property>
</bean> <!-- 使用 p 命名空间
给Entity 对象 的intValue 字段设置 为2 ,根据名称匹配SpEL对象
自动装配 autowire (不常用)
byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.反之不能
byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, 不能执行自动装配.
-->
<bean id="entity2" class="com.itdragon.spring.my.Entity"
p:intValue="2" autowire="byName" /> <!-- 继承 依赖
如果 被继承的bean 不想被继承,则要加上 abstract="true"
依赖:如果被依赖的bean,没有实例化,则会报错。如果有多个依赖需用","分开
-->
<bean id="entity3" class="com.itdragon.spring.my.Entity"
parent="entity" depends-on="spELEntity" /> <!-- 使用外部属性文件 在Spring操作数据库的时候再讲 -->
</beans>

实体类Entity和SpELEntity

import java.util.List;
import java.util.Map;
public class Entity { private int intValue;
private float floatValue;
private String stringValue;
private SpELEntity spELEntity;
private Map<String, Object> mapValue;
private List<Object> listValue; public Entity() {
}
public Entity(float floatValue, String stringValue) {
this.floatValue = floatValue;
this.stringValue = stringValue;
}
public int getIntValue() {
return intValue;
}
public void setIntValue(int intValue) {
this.intValue = intValue;
}
public float getFloatValue() {
return floatValue;
}
public void setFloatValue(float floatValue) {
this.floatValue = floatValue;
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
public SpELEntity getSpELEntity() {
return spELEntity;
}
public void setSpELEntity(SpELEntity spELEntity) {
this.spELEntity = spELEntity;
}
public Map<String, Object> getMapValue() {
return mapValue;
}
public void setMapValue(Map<String, Object> mapValue) {
this.mapValue = mapValue;
}
public List<Object> getListValue() {
return listValue;
}
public void setListValue(List<Object> listValue) {
this.listValue = listValue;
}
@Override
public String toString() {
return "Entity [intValue=" + intValue + ", floatValue=" + floatValue
+ ", stringValue=" + stringValue + ", spELEntity=" + spELEntity
+ ", mapValue=" + mapValue + ", listValue=" + listValue + "]";
}
}
public class SpELEntity {  

    private int intSpel;
private float floatSpel;
private boolean bSpel;
private String stringSpel;
public int getIntSpel() {
return intSpel;
}
public void setIntSpel(int intSpel) {
this.intSpel = intSpel;
}
public float getFloatSpel() {
return floatSpel;
}
public void setFloatSpel(float floatSpel) {
this.floatSpel = floatSpel;
}
public boolean isbSpel() {
return bSpel;
}
public void setbSpel(boolean bSpel) {
this.bSpel = bSpel;
}
public String getStringSpel() {
return stringSpel;
}
public void setStringSpel(String stringSpel) {
this.stringSpel = stringSpel;
}
@Override
public String toString() {
return "SpELEntity [intSpel=" + intSpel + ", floatSpel=" + floatSpel
+ ", bSpel=" + bSpel + ", stringSpel=" + stringSpel + "]";
} }

测试Main方法。首先要创建一个容器,然后通过bean的id获取到实例,这样就可以开始相关的操作。其中entity,entity2,entity3对应三块不同的知识点。

import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main { public static void main(String[] args) {
/**
* ClassPathXmlApplicationContext:从 类路径下加载配置文件,建议用该方法
* FileSystemXmlApplicationContext: 从文件系统中加载配置文件
*/
// 1. 创建 Spring 的 IOC 容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); /**
* entity 属性注入,构造器注入,对象引用,集合,SpEL,(重点)
* entity2 自动装配和P命名空间
* entity3 继承和依赖,作用域
*/
// 2. 从 IOC 容器中获取 bean 的实例
Entity entity = (Entity) ctx.getBean("entity"); // 3. 使用 bean
System.out.println(entity.toString());
// System.out.println(ctx.getBean("entity") == ctx.getBean("entity")); 使用 prototype 打印的是false ctx.close();
} }
Entity [intValue=1, floatValue=1.1, stringValue=<ITDragon>, spELEntity=SpELEntity [intSpel=1, floatSpel=1.2, bSpel=true, stringSpel=Spring4基础教程], mapValue={one=1, two=2}, listValue=[欢迎阅读, ITDragon, 的博客!]]

基于注解的Bean配置

相对于xml的配置,注解的方式显得异常简单。主要分两个步骤

第一步:在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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描指定目录下的包
resource-pattern="xxx/*.class" 属性过滤特定的类
-->
<context:component-scan base-package="com.itdragon.spring.my" >
<!-- annotation 是针对指定的类 和 assignable 是针对所有继承或者扩展该类的类-->
<!-- context:exclude-filter 只排除expression里面的内容
<context:exclude-filter type="annotation" expression=""/>
-->
<!-- context:include-filter 只包含expression里面的内容
需配合 use-default-filters="false"(默认是true) 一起使用
<context:include-filter type="annotation" expression=""/>
-->
</context:component-scan> </beans>

第二步:在对象上用注解。这四几个注解的作用一样,只是为了结构清晰,取的名字不同罢了。

使用方法很简单:直接在类上加注解即可。无参数的情况,bean的id默认是小写字母开头的类名。也可以指定参数@Commponent("指定参数"),那bean的id就是指定参数。

@Component: 基本注解, 标识了一个受 Spring 管理的组件

@Respository: 标识持久层组件

@Service: 标识服务层(业务层)组件

@Controller: 标识表现层组件

public interface AnnoRepository {  

    public void hello();  

}
import org.springframework.stereotype.Repository;
@Repository
public class AnnoRepositoryImp implements AnnoRepository{ @Override
public void hello() {
System.out.println("AnnoRepository : hello!");
} }
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AnnoService { @Autowired
private AnnoRepository annoRepository; public void hello() {
System.out.println("AnnoService : hello!");
annoRepository.hello();
} }
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; @Controller
public class AnnoController { @Autowired
private AnnoService annoService; public void execut() {
System.out.println("AnnoController : hello !");
annoService.hello();
} }

这里还有一个注解Autowired, context:component-scan 元素会自动组件装配被Autowired修饰的对象。

测试类:虽然applicationContext.xml中没有annoController的bean配置,但我们有注解!

import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main { public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
AnnoController annoController = (AnnoController) ctx.getBean("annoController");
annoController.execut();
ctx.close();
} }
AnnoController : hello !
AnnoService : hello!
AnnoRepository : hello!

有没有觉得基于注解的bean配置比基于xml的bean配置简单很多。


IOC容器Bean的生命周期

  • step1 实例化,通过构造器创建 Bean 实例
  • step2 赋值,为 Bean 的属性设置值
  • step3 init-method,调用 Bean 的初始化方法(init-method)
  • step4 destroy-method,当容器关闭时, 调用 Bean 的销毁方法(destroy-method)

以上代码都是笔者亲测可用的,不要嫌麻烦,麻烦是学不好的,如果有什么问题和建议可以留言,我会及时处理。http://blog.csdn.net/qq_19558705/article/details/49994191

Spring4 IOC详解的更多相关文章

  1. Spring4 JDBC详解

    Spring4 JDBC详解 在之前的Spring4 IOC详解 的文章中,并没有介绍使用外部属性的知识点.现在利用配置c3p0连接池的契机来一起学习.本章内容主要有两个部分:配置c3p0(重点)和 ...

  2. Spring4 AOP详解

    Spring4 AOP详解 第一章Spring 快速入门并没有对Spring4 的 AOP 做太多的描述,是因为AOP切面编程概念不好理解.所以这章主要从三个方面详解AOP:AOP简介(了解),基于注 ...

  3. spring4配置文件详解

    转自: spring4配置文件详解 一.配置数据源 基本的加载properties配置文件 <context:property-placeholder location="classp ...

  4. Spring IoC详解

    Spring IoC详解 1. 控制反转 控制反转是一种通过描述(XML或者注解)并通过第三方去产生或获取特定对象的方式.在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Depend ...

  5. IOC详解

    Ioc--控制反转详解(转载  http://www.cnblogs.com/qinqinmeiren/archive/2011/04/02/2151697.html) 本文转载与百度知道,简单例子让 ...

  6. (二)Spring 之IOC 详解

    第一节:spring ioc 简介 IOC(控制反转:Inversion of Control),又称作依赖注入dependency injection( DI ),是一种重要的面向对象编程的法则来削 ...

  7. NET笔记——IOC详解和Unity基础使用介绍

    说起IOC,可能很多初学者不知道是用来做什么的,今天正好有点时间,就来扫扫盲,顺便巩固下自己. IOC全称是Inversion Of Control,意为控制反转(这些自然百度也有),可什么是控制反转 ...

  8. 2、Spring的 IoC详解(第一个Spring程序)

    Spring是为了解决企业应用开发的复杂性而创建的一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架.在这句话中重点有两个,一个是IoC,另一个是AOP.今天我们讲第一个IoC. IoC概念 ...

  9. Spring之IOC详解

    学过Spring的小伙伴对于IOC一定不陌生,IOC:控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spr ...

随机推荐

  1. VS2015智能提示由英文改为中文

    使用 VS2015 时,在 4.0 下智能提示显示中文,在 4.5 下显示英文,对于我这种爱(ying)国(yu)人(tai)士(lan)来说,用起来太不方便了,于 是在 知乎 上找到个好方法如下: ...

  2. Django REST FrameWork中文教程3:基于类的视图

    我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图.我们将看到这是一个强大的模式,允许我们重用常用功能,并帮助我们保持代码DRY. 使用基于类的视图重写我们的API 我们将首先将根视 ...

  3. Object类—复写equals方法,hashCode方法,toString方法

    Object:所有类的根类. Object是不断抽取而来,具备着所有对象都具备的共性内容. class Person extends Object { private int age; Person( ...

  4. Java集合源码分析(一)ArrayList

    前言 在前面的学习集合中只是介绍了集合的相关用法,我们想要更深入的去了解集合那就要通过我们去分析它的源码来了解它.希望对集合有一个更进一步的理解! 既然是看源码那我们要怎么看一个类的源码呢?这里我推荐 ...

  5. 系统装机硬盘格式 >> GPT或者UEFI

    预装Win8系统的电脑,硬盘都是采用这种分区格式,因为出厂安装时,是以Uefi方式启动安装的. 简单的办法,仍安装Win8系统:或者是转换磁盘分区格式为MBR,不用任何软件就可实现,需要重建分区表,会 ...

  6. php中常用的字符串格式化函数

    ltrim():从字符串左删除空格或其他预定义字符串 rtrim():从字符串的末端开始删除空白字符串或其它预定义字符 trim():从字符串的两端删除空白字符和其他预定字符 str_pad():把字 ...

  7. Android性能优化之启动速度优化

    Android性能优化之启动速度优化   Android app 启动速度优化,首先谈谈为什么会走到优化这一步,如果一开始创建 app 项目的时候就把这个启动速度考虑进去,那么肯定就不需要重新再来优化 ...

  8. js-自定义事件

    1.自定义事件 开发人员自己定义的事件,是除了系统以外的事件. 可以供其他开发人员使用,有利于多人写作开发,可扩展js的原有事件. 需要:事件绑定器.事件触发器 2.自定义事件三要素 ①:对象.事件名 ...

  9. bug:未考虑实际使用场景

    最近bug比较多,汗颜. 1.需求背景 (1)app活动页面,用户参与并完成能够以1分钱价格购买指定商品(2)这个页面可分享至app以外的渠道,如微信.QQ等 2.这个bug的表现形式:用户在第三方渠 ...

  10. 分布式数据库TiDB的部署

    转自:https://my.oschina.net/Kenyon/blog/908370 一.环境 CentOS Linux release 7.3.1611 (Core)172.26.11.91   ...