您的位置:首页 > 编程语言 > Java开发

Spring(一)Spring IOC容器配置详解——基于xml文件形式

2015-01-24 20:19 549 查看

一、Spring

Spring是一个轻量级的框架,相当于一个平台性质,大大简化了Java企业级应用的开发,提供了强大的、稳定的功能。Spring框架大约由20个功能模块组成,这些模块被分为6个部分,如图所示:



Spring Core是最基础部分,提供了IOC特性;Spring AOP是基于Spring Core的符合规范的面向切面编程的实现。

Spring IOC容器是Spring最核心的部分,IOC(Inversion of Control),控制反转,也被称为依赖注入,是面向对象编程中的一种设计理念,用来降低程序代码之间的耦合度。

通俗点讲,在实际应用中,多个类之间需要互相依赖才能完成某些特定的业务,而依赖注入就是以配置文件的方式来维护类与类之间的关系,而非硬编码,从而降低了系统之间的耦合,增大了可维护性。

二、搭建环境

先来一个简单的HelloWorld

1.下载spring的jar包:http://projects.spring.io/spring-framework/(本文使用的是4.1.4的版本)

2.创建普通的java项目(不一定非得是web项目,简单起见)

3.添加jar包:

spring-aop-4.1.4.RELEASE.jar
spring-beans-4.1.4.RELEASE.jar
spring-context-4.1.4.RELEASE.jar
spring-context-support-4.1.4.RELEASE.jar
spring-core-4.1.4.RELEASE.jar
spring-expression-4.1.4.RELEASE.jar
commons-logging.jar//此jar包为第三方类库,需要自行下载


4.src下创建spring-config.xml文件(名字可以自己取),创建Student类、test类

(1)Student类:

package com.wzj.entity;

public class Student {
private int id;
private String name;

//省略get、set方法
//为了方便显示,重写了toString方法
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}


(2)spring-config.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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p-4.0.xsd">

<!-- 以这种方式来声明Student类的实例 -->
<bean id="student" class="com.wzj.entity.Student">
<!-- 为Student对象的属性赋值 -->
<property name="id" value="1"/>
<property name="name" value="张三"/>
</bean>
</beans>


(3)test类:

package com.wzj.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wzj.entity.Student;

public class Test {

public static void main(String[] args) {
//通过ApplicationContext接口的实现类实例化Spring上下文对象
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
//通过getBean()方法来获取到Student类的对象
Student student=(Student)context.getBean("student");
System.out.println(student);
}

}


(4)运行结果:Student [id=1, name=张三]

三、Bean配置

1.BeanFactory和ApplicationContext

Spring框架提供了两种IOC容器的实现:

(1)BeanFactory:IOC容器的基本实现

(2)ApplicationContext(推荐使用):提供了更多的高级特性,是BeanFactory的子接口

BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;


ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory

ApplicationContext的实现类:

—— ClassPathXmlApplicationContext:从 类路径下加载配置文件

—— FileSystemXmlApplicationContext: 从文件系统中加载配置文件

2.配置Bean——基于xml文件的形式

(1)在spring配置文件中以<bean>元素来配置Bean实例,如:

<!--
id:Bean的名称,在IOC容器中必须是唯一的,还可以指定多个名字,名字之间用英文逗号、分号或空格隔开
class:Bean所对的类的全名,其实内部是通过反射来动态创建对象的
-->
<bean id="student" class="com.wzj.entity.Student">
<!-- 为Student对象的属性赋值,value也可以作为子标签 -->
<property name="id" value="1"/>
</bean>


(2)获取bean实例:

//getBean()的参数名称要和配置文件中bean的id对应
Student student=(Student)context.getBean("student");
在spring 4以上版本,支持直接传递类型,不用强制转换,不过为了和低版本兼容,慎用:

Student student=context.getBean("student",Student.class);

3.依赖注入的方式:

Spring支持3中依赖注入的方式:

—— 属性注入(最常用)

—— 构造器注入

—— 工厂方法注入(很少使用,不推荐)

(1)属性注入:

<property name="name" value="张三"></property>
value也可以作为子标签:

<property name="name">
<value>张三</value>
</property>


(2)构造器注入:

①按索引匹配入参

<bean id="student" class="com.wzj.entity.Student">
<constructor-arg value="" index="0"></constructor-arg>
</bean>
index属性:表示参数的顺序(可以不写,但是顺序要一致,最好写上)

②按类型匹配入参

如果说类中不止有一个构造方法的时候,为了防止容器不知道调用哪个,可以为参数指定类型type(方法重载的区别不就是看参数的区别么)
<constructor-arg value="" type=""></constructor-arg>

type和index可以混合使用

4.依赖注入不同的数据类型:

(1)注入直接量(基本数据类型、字符串)

直接在value属性中书写值,若包含特殊符号,可以使用一下方式转义:

<value><![CDATA[这里写值]]></value>

(2)引用其他bean组件

①引用外部已定义好的bean:

创建Teacher类,Student类中包含Teacher的属性,配置:

<bean id="teacher" class="com.wzj.entity.Teacher">
<property name="id" value="3"/>
<property name="name" value="张老师"/>
</bean>
<bean id="student" class="com.wzj.entity.Student">
<!-- 使用ref属性引用其他bean,也可以作为子标签使用 -->
<property name="teacher" ref="teacher" />
</bean>


②定义内部bean:

可以直接在属性中创建内部Bean,不能被外部引用

<bean id="student" class="...">
<property name="teacher">
<bean class="...Teacher">
<!-- 省略里面的配置-->
</bean>
</property>
</bean>
同样如果使用构造器注入的方式,同样使用ref属性进行引用。

(3)注入null和空字符串

①如果有时候想给实例的某些属性赋null值(当然,不赋值也是null值),这时候就可以使用到null值的特有标签<null/>

<property name="propertyName"><null/></property>
②使用<value></value>方式注入空字符串

(4)为级联属性注入值

Student类中包含Teacher类的属性,此时可以再student的bean中为teacher属性的属性赋值,这种方式很少使用,也不建议使用

<bean id="student" class="com.wzj.entity.Student">
<property name="teacher" ref="teacher"></property>
<property name="teacher.name" value="张老师"></property>
</bean>
注意:为teacher的属性赋值前,teacher属性一定要初始化,不然会抛异常

(5)注入集合属性

①list

假如Teacher类中包含着一个List<Student> students属性,则此时就可以使用list标签

<bean id="teacher" class="com.wzj.entity.Teacher">
<property name="students">
<list>
<ref bean="student1"/>
<ref bean="student2"/>
<ref bean="student3"/>
</list>
</property>
</bean>
在list标签中可以使用<ref/>、<value/>以及内部<bean>标签

②Map

①使用entry作为map的子节点,假如在Teacher类中有一个Map<String,Student>类型的students属性

<property name="students">
<map>
<entry key="AA" value-ref="student1"></entry>
<entry key="BB" value-ref="student2"></entry>
<entry key="CC" value-ref="student3"></entry>
</map>
</property>
value、或者其他什么内部Bean、构造器等等的使用方式跟前面一样。

③java.util.Properties

<property name="students">
<props>
<prop key="键">值</prop>
<prop key="键">值</prop>
</props>
</property>
每个prop子标签必须定义key属性

(6)在外部配置单利的List,供多个bean使用:

①导入命名空间:

xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation中添加:
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
②使用util:list标签

<util:list id="list">
<!-- ref、value、或者内部Bean等使用方式 -->
</util:list>

5.使用p命名空间简化配置

使用p空间可以简化配置文件,需导入命名空间:xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation中添加:
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p-4.0.xsd
使用:

<bean id="student" class="com.wzj.entity.Student" p:name="name值" p:teacher-ref="teach引用"></bean>

6.自动装配

spring IOC容器可以为我们自动装配,只需要在bean的autowire属性里指定自动装配模式

(1)byType(根据类型自动装配):

若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法 判定哪个 Bean 最合适该属性, 所以不能执行自动装配.
(2)byName(根据名称自动装配):

必须将目标 Bean 的名称和属性名设置的完全相同.
(3)constructor(通过构造器自动装配):

当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用
例:<bean autowire="byName">..</bean>

7.Bean之间的关系

继承、依赖关系,但是这种关系不是面向对象中的继承,是配置之间的继承

(1)继承

①可以使用Bean元素的parent属性指定其父Bean,则其成为子Bean

②子Bean可以继承父Bean的配置,也可以覆盖父Bean的配置

③父Bean也可以作为一个模板,使用abstract="true"设置,此时这个父Bean不能被实例化,只能当配置模板被继承(类似于Java中的抽象类)

④如果说一个bean的class属性没有设置,那么这个bean必须是一个模板bean(即abstract为true)

⑤不是父Bean所有的属性子Bean都能继承,比如:abstract="true",autowire等

(2)依赖

1.spring可以通过depends-on属性指定这个bean依赖的bean,如果说spring配置中不存在被依赖的bean,则初始化这个Bean的时候就会报错。

2.如果前置依赖于多个Bean,则可以通过逗号、空格的方式配置Bean的名称。

8.Bean的作用域

使用Bean元素的scope属性来配置作用域

(1)singleton:默认值,容器初始化时创建实例,在整个生命周期中只创建一个实例,单例!

(2)prototype:原型的,容器初始化时不创建实例,而在每次使用getBean的时候都创建一个新的实例、

(3)request:没次Http请求时都创建一个新的Bean,该作用域仅作用域WebApplicationContext环境

(4)session:同一个HttpSession共用一个Bean,不同的session使用不用的Bean

9.使用外部属性文件:

有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离;Spring 提供了一个PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器

使用方式:

(1)创建一个属性文件,比如db.properties:
driverclass=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=scott
password=tiger
(2)在spring配置文件中导入context命名空间后首先配置:

<!--导入属性文件-->
<context:property-placeholder location="classpath:db.properties"/>

然后使用的时候使用${var}的方式:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- 指定驱动类 -->
<property name="driverClassName" value="${driverclass}"/>
</bean>

10.spEL

即spring表达式语言,是一个支持运行时查询和操作对象图的强大的表达式语言

SpEL 使用 #{…} 作为定界符


(1)使用spel赋字面量的值

①整数:<property name="n" value="#{5}"/>

②小数:<property name="num" value="#{89.7}"/>

③科学计数法:<property name="capacity" value="#{1e4}"/>

④String可以使用单引号或者双引号作为字符串的定界符号:

<property name="name" value="#{'Jack'}"/> 或 <property name='name' value='#{"Jack"}'/>

⑤Boolean:<property name="enabled" value="#{false}"/>

(2)使用spel引用其他Bean、Bean属性、方法

比如引用其他Bean属性:

<property name="name" value="#{teacher.name}"></property>
其他使用类似

(3)spel支持运算符、正则表达式等

①算数运算符:

<property name="count" value="#{students.count+10}"></property>
②加号还可以作为字符串连接:

<property name="name" value="#{stu.firstname+''+stu.lastname}"/>
③比较运算符:<, >, ==, <=, >=, lt, gt, eq, le, ge

④逻辑运算符:and, or, not,|

⑤三元运算符:?:

⑥正则表达式:matches

<property name="name" value="#{admin.email matches '正则表达式内容'} "/>

(4)通过T()方式调用一个类的静态方法,返回一个Class Object,然后再调用相应的方法,例如:

<property name="..." value="#{T(java.lang.Math).PI}"></property>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: