Spring启动时,读取应用程序提供的Bean配置信息,并在Spring容器中提供一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。
Bean配置信息是Bean的元数据信息,由以下4个方面组成
Spring元数据信息在Spring容器中的内部对应由一个个BeanDefinition行程的Bean注册表。
Spring支持多种形式的Bean配置方式。
Bean配置信息 首先定义了Bean的实现及依赖关系,Spring容器根据Bean的配置信息在容器内部建立Bean定义注册表, 然后根据注册表加载、实例化Bean,并建立Bean之间的依赖关系, 最后将这些准备就绪的Bean放到Bean缓存池中,供外层的应用调用。
基于XML的配置,spring1.0的配置文件采用DTD格式,Spring2.0以后则采用Schema形式,基于Schema形式,让不同类型的配置拥有了自己的命名空间,更具扩展性。此外,Spring基于Schema配置方案为许多领域的问题提供了简化的配置方法,配置工作因此得到了大幅简化。
解析:
命名空间的定义分为两个步骤: 第一步指定命名空间的名称, 第二步指定命名空间的Schema文档样式文件的位置,用空格或回车换行进行分隔。
命名空间使用全限定名,每个组织机构在发布Schema文件后,都会为该Schema文件提供一个引用的URL地址,一般使用这个URL地址指定命名空间对应的Schema文件。
命名空间名称和对应的Schema文件地址之间使用空格或回车分隔,不同的命名空间之间也使用这种分隔方法。
指定命名空间的Schema文件地址有两个用途:
Spring4.0配置的Schema文件放在各模块Jar文件内一个名为config的目录下
比如AOP:
强烈建议使用新的基于Schema的配置方式
除了Xml的配置方式,spring还支持基于注解、Java类、Groovy的配置方式,本质上是相同的,仅仅是形的区别。
基于Xml的配置方式是最基础、最传统的配置方式,下面我们注重探讨基于Xml的配置,另外三种也作简要介绍。
在Spring容器的配置文件中定义一个简要的Bean的配置片段如下
id="plane" class="com.xgj.Plane">
我们用STS创建一个Maven工程如下:举例:
logback.xml没用,使用的log4j的配置那文件
package com.xgj.ioc.beans;
public class Boss {
private String name;
private String sex;
private int age;
private Plane plane ;
....省略setter/getter
public void introduce() {
System.out.println("Boss Information【name:" + name + ",sex:" + sex + ",age:" + age +"】" );
plane.info();
}
}
package com.xgj.ioc.beans;
public class Plane {
private String brand;
private String color;
private int speed;
....省略setter/getter
public void info(){
System.out.println("brand:" + brand + ",color:" + color + ",speed" + speed);
}
}
package com.xgj.ioc.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// 加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:spring/application-config.xml");
// 从容器中获取实例化后的bean
Boss boss = ctx.getBean("boss", Boss.class);
Plane plane = ctx.getBean("plane", Plane.class);
// 设置属性
boss.setName("XGJ");
boss.setSex("MALE");
boss.setAge(20);
boss.setPlane(plane);
// 设置属性
plane.setBrand("A380");
plane.setColor("red");
plane.setSpeed(900);
// 调用方法
boss.introduce();
}
}
application-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="plane" class="com.xgj.ioc.beans.Plane"/>
<bean id="boss" class="com.xgj.ioc.beans.Boss"/>
beans>
一般情况下,在配置一个Bean时,需要为其指定一个id属性作为Bean的名称。
id在IoC容器中必须是唯一的,并且id的命名需要满足XML对id的命名规范(id是xml规定的特殊属性)
在实际情况下,id命名约束并不会给用户带来影响,如果用户确实希望用一些特殊字符进行bean命名,这可以使用的name属性。 name属性没有字符上的限制,几乎可以使用任何字符比如?ab、123
id和name都可以指定多个名字,名字之间可以用逗号、分号或者空格进行分隔,比如
id="plane" name="#plane1,123,$plane" class="com.xgj.ioc.beans.Plane"/>
用户可以通过getBean(“#plane1”),getBean(“123”),getBean(“$plane”),获取IoC容器中的plane Bean.
Spring配置文件不允许出现两个相同id的bean, 但可以出现两个相同name的bean。
如果有多个相同name的bean,通过getBean(BeanName)则获取的是后面声明的那个Bean。
为了避免此问题,应尽量使用ID,而非Name来命名Bean。
如果id和name均未指定,比如
class="com.xgj.ioc.beans.Plane"/>
Spring会指定将全限定类名作为bean的名称,用户可以通过getBean(“com.xgj.ioc.beans.Plane”)获取Bean
如果存在多个实现类相同的匿名Bean,如下
<bean class="com.xgj.ioc.beans.Plane"/>
<bean class="com.xgj.ioc.beans.Plane"/>
<bean class="com.xgj.ioc.beans.Plane"/>
第一个Bean可以通过getBean(“com.xgj.ioc.beans.Plane”)获得 第二个Bean通过getBean(“com.xgj.ioc.beans.Plane#1”)获得 第三个Bean通过getBean(“com.xgj.ioc.beans.Plane#2”)获得
一般匿名bean在通过内部Bean为外层Bean提供注入值是使用,类似Java的匿名类。
上面各种命名方式,只是为了演示Sping配置的灵活性和包容性,实际应用中并不多见, 通过id为Bean指定唯一的名称才是正解。