目录
1.获取bean的三种方式
1.1、根据id获取
由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象。这种获取的对象默认是Object类型,需要强转为需要的类型。
<bean id="studentOne" class="com.itwpf.spring.pojo.Student"></bean>
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean
//根据 id
Student studentOne = (Student)ioc.getBean("studentOne");
System.out.println(studentOne);
}
1.2、根据类型获取
<bean id="studentTwo" class="com.itwpf.spring.pojo.Student"/>
@Test
public void testIOC(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean
//根据类型
Student studentTwo = ioc.getBean(Student.class);
Student studentThree = ioc.getBean("studentOne", Student.class);
System.out.println(studentThree);
}
注意:根据类型获取bean时,要求ioc容器中有且只有一个类型匹配的bean
若没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
若有多个类型匹配的bean,此时抛出异常:NoUniqueBeanDefinitionException
1.3、根据id和类型获取
<bean id="studentThree" class="com.itwpf.spring.pojo.Student"/>
@Test
public void testDI(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Student studentTwo = ioc.getBean("studentTwo", Student.class);
Student studentThree = ioc.getBean("studentSix", Student.class);
System.out.println(studentThree);
}
1.4、扩展
如果组件类实现了接口,可以根据接口类型获取bean,前提是bean唯一
如果一个接口有多个实现类,这些实现类都配置了bean,就不能根据接口获取bean,因为bean不唯一。
1.5、结论
根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类 型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。
(instanceof用法,是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。)
2.依赖注入之setter注入
1.1、创建学生类Student
public class Student {
private Integer id;
private String name;
private Integer age;
private String sex;
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
1.2、配置bena时为属性赋值
<bean id="studentTwo" class="com.itwpf.spring.pojo.Student">
<!--
property:通过成员变量的set方法进行赋值
name:指定属性名(是通过setXXX() getXxx()获取的,与成员变量无关
value:指定属性值
-->
<property name="sid" value="1001"></property>
<property name="sname" value="张三"></property>
<property name="age" value="23"></property>
<property name="gender" value="男"></property>
</bean>
1.3、测试
@Test
public void testDIBySet(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student studentTwo = ac.getBean("studentTwo", Student.class);
System.out.println(studentTwo);
}
3.依赖注入之构造器注入
3.1、在Student类中添加有参构造
public Student(Integer id, String name, Integer age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
3.2、配置bean
<bean id="studentThree" class="com.itwpf.spring.pojo.Student">
<constructor-arg value="1002" name="sid"></constructor-arg>
<constructor-arg value="李四" index="1"/>
<constructor-arg value="24"/>
<constructor-arg value="女"/>
</bean>
注意:constructor-arg标签还有两个属性可以进一步描述构造器参数:
index属性:指定参数所在位置的索引(从0开始)
name属性:指定参数名
3.3、测试
@Test
public void testDIBySet(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student studentTree = ac.getBean("studentTree", Student.class);
System.out.println(studentTree);
}
4.特殊值处理
4.1、字面量赋值
什么是字面量?
int a = 10; 声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a 的时候,我们实际上拿到的值是10。 而如果a是带引号的:'a',那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面量没有引申含义,就是我们看到的这个数据本身。
<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>
4.2、null值
<property name="name">
<null />
</property>
注意,下面这种写法,为name所赋的值是字符串
<property name="name" value="null"></property>
4.3、xml实体
<!-- 小于号在XML文档中用来定义标签的开始,不能随便使用 -->
<!-- 解决方案一:使用XML实体来代替 -->
<!--
&: &
单引号('): '
大于(>):&gt;
小于(<):&lt;
双引号("):&quot;
-->
<property name="expression" value="a < b"/>
4.4、CDATA节
在idea中直接打出大写的CD就可以快速构建
<property name="expression">
<!-- 解决方案二:使用CDATA节 -->
<!-- CDATA中的C代表Character,是文本、字符的含义,CDATA就表示纯文本数据 -->
<!-- XML解析器看到CDATA节就知道这里是纯文本,就不会当作XML标签或属性来解析 -->
<!-- 所以CDATA节中写什么符号都随意 -->
<value><![CDATA[a < b]]></value>
</property>
5.为类类型属性赋值
5.1、创建班级类Clazz
public class Clazz {
private Integer cid;
private String cname;
@Override
public String toString() {
return "Clazz{" +
"cid=" + cid +
", cname='" + cname +
'}';
}
public Clazz() {
}
public Clazz(Integer cid, String cname) {
this.cid = cid;
this.cname = cname;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
5.2、修改Student类
在Student类中添加以下代码:
private Clazz clazz;
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
5.3、方式一:引用外部已声明的bean
配置Clazz类型的bean
<bean id="clazzOne" class="com.atguigu.spring.bean.Clazz">
<property name="clazzId" value="1111"></property>
<property name="clazzName" value="306班"></property>
</bean>
为Student中的clazz赋值
<bean id="studentFour" class="com.atguigu.spring.bean.Student">
<property name="id" value="1004"></property>
<property name="name" value="赵六"></property>
<property name="age" value="26"></property>
<property name="sex" value="女"></property>
<!-- ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值 -->
<property name="clazz" ref="clazzOne"></property>
</bean>
如果错把ref属性写成了value属性,会抛出异常: Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.atguigu.spring.bean.Clazz' for property 'clazz': no matching editors or conversion strategy found
意思是不能把String类型转换成我们要的Clazz类型,说明我们使用value属性时,Spring只把这个 属性看做一个普通的字符串,不会认为这是一个bean的id,更不会根据它去找到bean来赋值
5.4、方式二:内部bean
<bean id="studentFour" class="com.atguigu.spring.bean.Student">
<property name="id" value="1004"></property>
<property name="name" value="赵六"></property>
<property name="age" value="26"></property>
<property name="sex" value="女"></property>
<property name="clazz">
<!-- 在一个bean中再声明一个bean就是内部bean -->
<!-- 内部bean只能用于给属性赋值,不能在外部通过IOC容器获取,因此可以省略id属性 -->
<bean id="clazzInner" class="com.atguigu.spring.bean.Clazz">
<property name="clazzId" value="2222"></property>
<property name="clazzName" value="307班"></property>
</bean>
</property>
</bean>
5.5、方式三:级联属性赋值
级联赋值,是更新数据,更新所引用的bean所赋的值
<bean id="studentFour" class="com.atguigu.spring.bean.Student">
<property name="id" value="1004"></property>
<property name="name" value="赵六"></property>
<property name="age" value="26"></property>
<property name="sex" value="女"></property>
<!-- 一定先引用某个bean为属性赋值,才可以使用级联方式更新属性 -->
<property name="clazz" ref="clazzOne"></property>
<property name="clazz.clazzId" value="3333"></property>
<property name="clazz.clazzName" value="308班"></property>
</bean>
<bean id="clazzOne" class="com.atguigu.spring.bean.Clazz">
<property name="clazzId" value="1111"></property>
<property name="clazzName" value="306班"></property>
</bean>