文章目录
命名空间
下面列出了比较常用的几个,不用全部引入,用到那个引入那个即可,其中只有 p 是没有 xsi:schemaLocation 的,其他都是两两成对出现,一个 key,一个是 value。
<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:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
bean 标签
id 和 class 属性
bean 标签最常用的两个属性就是 id 和 class 属性了。
<bean id="obj1" class="model.PersonModel"></bean>
从效果来说,上面的配置代码和下面的 Java 代码一样,都是生成了一个 PersonModel 的实例 obj1
PersonModel obj1 = new PersonModel();
从过程来说的话,Spring 配置文件中的代码是用反射来实现的,先获取 bean 标签的 id 和 class 属性值字符串,然后根据反射创建对象,见下面代码。当然 Spring 实际的代码肯定是很完善的。
String idStr = "";
String classStr = "";
Class clazz = Class.forName(classStr);
Object obj1 = clazz.newInstance();
container.put(idStr,obj1);
注意事项:
- 一个 XML 文件中,id 是唯一的,就如同在一个 Java 类中,变量名不能重复。
- class 的值是全类名
验证:怎么验证 bean 已经创建好对象呢?可以在 Java 端模拟一个 Spring 容器来验证
public static void main(String[] args) {
// 模拟 Spring 容器,
// ClassPathXMLApplicationContext的参数是从资源文件夹到Spring配置文件的路径
ApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
// 从 Spring 容器中获取变量obj1
Object obj1 = context.getBean("obj1");
Demo1 pm = (Demo1) obj1;
System.out.println(pm);
}
设置对象的属性值
1. property 子标签
使用 name、value、ref 属性
在 <bean>标签中,有个子标签<property>,这个标签用于设置对象的属性,property 标签需要在实体类中实现 set 方法。
该标签有几个重要的属性 —— name、value、ref。
value 属性是简单数据类型的属性,value 创建新对象
<bean id="obj2" class="model.Demo1">
<property name="age" value="12"></property>
</bean>
上面的 bean 标签相当于下面的 Java 代码
obj2.setAge("12");
ref 属性是设置引用数据类型属性,ref 引用的是已经存在的对象。
<bean id="obj3" class="model.Demo2">
<property name="ddd" ref="obj2"></property>
</bean>
obj3.setDdd(obj2);// obj2 是 Demo1 类的对象
注意事项:
- 使用 property 标签设置属性,必须要有该属性的 set 方法,否则会抛出无法写入属性的异常:
org.springframework.beans.NotWritablePropertyException
2. 省略格式
使用这种方法,需要在 beans 根标签中添加命名空间
xmlns:p="http://www.springframework.org/schema/p"
使用时的语法:<bean id="" class="" p:属性1="" p:属性2="" ...></bean>
,如果是注入的话,需要在属性后面加上-ref
<bean id="obj5" class="model.Demo1" p:name="ooo" p:age="iii" p:d2-ref="obj3"></bean>
相当于
<bean id="obj5" class="model.Demo1">
<property name="name" value="ooo"></property>
<property name="age" value="iii"></property>
<property name="d2" ref="obj3"></property>
</bean>
PS:也是需要有对应属性的 set 方法,否则会抛异常
3. constructor-arg 子标签
在 <bean>标签中,有个子标签<constructor-arg>,该标签必须有对应的构造方法。
在 Demo1 中,定义一个如下所示的构造函数
public Demo1(String s1, String s2, Demo1 s3) {
name = s1;
age = s2;
System.out.println(s3.getAge());
}
<constructor-arg> 可以用 name、index 属性来指明要为构造方法的那个参数赋值,而 value、ref 属性和 property 标签中的 value、ref 属性一致。
<bean id="obj4" class="model.Demo1">
<constructor-arg name="s1" value="youka"></constructor-arg>
<constructor-arg index="1" value="20"></constructor-arg>
<constructor-arg index="2" ref="obj2"></constructor-arg>
</bean>
注意事项:
- 使用 ;constructor-arg 标签设置属性,必须要有构造方法,否则会抛出异常:
org.springframework.beans.NotWritablePropertyException
4. 集合注入
scope 属性
scope 属性取 singleton 表示单例,即在 Spring 容器中只允许创建该类的一个实例;取 prototype 表示多例,即从 Spring 容器中每次获取该类实例时,会创建一个新的实例。
默认情况:singleton
<bean id="obj3" class="model.Demo2" scope="singleton"></bean>
<bean id="obj4" class="model.Demo2" scope="prototype"></bean>
测试代码:
<bean id="s1" class="model.Demo1" scope="singleton"></bean>
Demo1 s1 = (Demo1) context.getBean("s1");
System.out.println(s1);
Demo1 s2 = (Demo1) context.getBean("s1");
System.out.println(s2);
scope 设置为 singleton:
将 scope 修改为为 prototype:
autowire 属性
autowire —— 自动装配/自动装载,指的是 Spring 可以自动从容器中找到需要的东西进行装配。主要的属性值有byName,和 byType。
- byName 就是按照(属性的)名字方式查找。
- byType 是按照(属性的)类型方式进行查找。
byName
public class Demo1 {
private String name;
private String age;
public void setName(String name) {
this.name = name;
}
public void setAge(String age){
this.age = age;
}
public class Demo2 {
private String ccc;
private Demo1 ddd;
public void setDdd(Demo1 ddd) {
this.ddd = ddd;
}
public void setHhh(String ccc){
this.ccc = ccc;
}
}
<bean id="ddd" class="model.Demo1" >
<property name="name" value="youka"></property>
<property name="age" value="22"></property>
</bean>
<bean id="obj6" class="model.Demo2" autowire="byName"></bean>
ApplicationContext context = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
Demo2 d6 = (Demo2) context.getBean("obj6");
System.out.println(d6);
结果:Demo2 [ddd=Demo1 [name=youka, age=22], hhh=null]
按照名字查找 按照 Demo2 类的属性名 ddd,从容器中查找相同名字并且可以给 ddd 属性赋值的对象。
和通过 ref 依赖注入的形式一样,只不过按名字自动装载的方式自动将 Spring 容器中 id 和 自动装载的对象的属性名相同的对象注入。
<bean id="ddd" class="model.Demo1" >
<property name="name" value="youka"></property>
<property name="age" value="22"></property>
</bean>
<bean id="obj6" class="model.Demo2">
<property name="ddd" ref="ddd"></property>
</bean>
- 如果容器中没有和属性名相同的对象,那么该属性的值为 null;
- 如果容器中存在和属性名相同的对象,但该对象不能给该属性赋值(和属性值类型相同,或者是属性值类型的子类的是可以给属性赋值的),那么会抛出异常
org.springframework.beans.ConversionNotSupportedException
byClass
按照类型查找就是按照属性的类型查找,需要注意的是,byType 使用是需要 Spring 容器中需要注入的对象对应的属性的类型必须要唯一,不唯一的话会 报出不唯一的异常org.springframework.beans.factory.NoUniqueBeanDefinitionException
constructor
除了上面两个属性值,autowire 还有个 constructor 属性,表示使用构造方法时,将方法的参数自动装载,它是通过属性类型查找的,和byType 差不多,了解即可。
小结
byName 自动装载,由于 Spring 中对象的 id 是唯一的,因此只需要关注 Spring 中的这个对象的类型和需要注入的对象的属性值类型是否可以转换
byType 自动装载,由于是按照类型查找,所以需要关注的是能否找到唯一的对象为其注入