目录
一、前言二、通过Setter方法配置Bean
三、通过构造器配置Bean
1. 通过属性名配置
2. 通过索引配置
3. 通过属性类型配置
四、通过p命名空间配置bean
五、引用/注入其他bean对象
六、引用/注入内部bean对象
七、引入/注入集合/数组类型
八、使用util名称空间
九、级联赋值
相关文章
【Spring(一)】如何获取对象(Bean) |
一、前言
上一篇文章中,我们对Spring做了一些基本的了解,以及在Spring中如何获取Bean。我们在XML配置文件中,只是写了那些标签和属性,但它们都各自代表什么、如何配置一个Bean、Bean的配置方式等,这些都是我们接下来需要了解和学习的。
在配置Bean的时候,我们首先得知道需要配置的那个类是什么。这就和我们用传统方式创建对象一样,通过类来创建一个对象。我们在下边的示例中都使用这个Monster类讲解。
package com.jl.spring.bean;
/**
* @author long
* @date 2022/8/30
*/
public class Monster {
private Integer monsterId;
private String name;
private String skill;
public Monster(){}
public Monster(Integer monsterId, String name, String skill) {
this.monsterId = monsterId;
this.name = name;
this.skill = skill;
}
public Integer getMonsterId() {
return monsterId;
}
public void setMonsterId(Integer monsterId) {
this.monsterId = monsterId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
@Override
public String toString() {
return "Monster{" +
"monsterId=" + monsterId +
", name='" + name + '\'' +
", skill='" + skill + '\'' +
'}';
}
}
二、通过Setter方法配置Bean
<bean class="com.jl.spring.bean.Monster" id="monster01">
<property name="monsterId" value="100"/>
<property name="name" value="牛魔王"/>
<property name="skill" value="芭蕉扇"/>
</bean>
-
class
是类的全路径,通过类的全路径我们的Spring容器才可以创建Bean对象。 -
id
是Bean的名称,我们可以通过id值来获取到这个Bean对象。 -
property
这个标签用来标识这是一个属性。 -
name
是属性的名称(我们的name值必须要和对象中的属性名
一致)。 -
value
是属性的值。
在上边的配置中,我们属性配置用的都是property
这个标签,而这个使用这个标签装配属性的前提是:我们的类必须提供相应的setter方法
和无参构造方法
。
⚠如果我们不提供属性相应的setter()
,那么就会出现下边的错误:
⚠如果不提供无参构造方法就会出现如下的错误:
三、通过构造器配置Bean
通过构造器配置器的一个前提就是:提供有参构造
。不提供就会报错。
通过构造器来配置Bean,一共有三种配置方式:通过属性名配置、通过索引来配置、通过类型来配置。
1. 通过属性名配置
<bean class="com.jl.spring.bean.Monster" id="monster02">
<constructor-arg name="monsterId" value="100"/>
<constructor-arg name="name" value="牛魔王"/>
<constructor-arg name="skill" value="芭蕉扇"/>
</bean>
这种方式和使用Setter()
方式来配置差不多,唯一的区别就是:我们使用有参构造
来配置Bean使用的标签是<constructor-arg>
。
2. 通过索引配置
<bean class="com.jl.spring.bean.Monster" id="monster02">
<constructor-arg value="200" index="0"/>
<constructor-arg value="白骨精" index="1"/>
<constructor-arg value="九阴白骨爪" index="2"/>
</bean>
使用索引配置Bean需要在<constructor-arg>
使用index
属性,index从0开始,对应我们有参构造函数中参数的顺序。
3. 通过属性类型配置
<bean class="com.jl.spring.bean.Monster" id="monster02">
<constructor-arg value="200" type="java.lang.Integer"/>
<constructor-arg value="白骨精" type="java.lang.String"/>
<constructor-arg value="九阴白骨爪" type="java.lang.String"/>
</bean>
之所以可以使用类型配置Bean,是因为Java中的重载中规定:不能有完全相同的属性类型。
四、通过p命名空间配置bean
这种方式,同样也要求类必须具备Setter()和无参构造
这两个条件。
在使用P命名空间前还需要再XML配置文件的头部添加相关的声明。xmlns:p="http://www.springframework.org/schema/p
<!--通过p命名空间来配置-->
<bean id="monster03" class="com.jl.spring.bean.Monster"
p:monsterId="500"
p:name="红孩儿"
p:skill="喷火"
/>
我们的这种方式,配置的时候是写在标签内的,而不是在标签体中。
五、引用/注入其他bean对象
我们在上边的学习的过程,属性都是基本数据类型的。但我们的使用过程中,一个对象的属性还有可能是其他我们自定义的对象类型。例如:Service调用Dao的时候,需要在Service层创建一个Dao对象。我们这里就讲解这种情况如何取解决。
当然,开始之前我们也得有两个类,来演示。
package com.jl.spring.dao;
/**
* @author long
* @date 2022/8/31
*/
public class MemberDAOImpl {
public MemberDAOImpl(){
System.out.println("MemberDAOImpl构造器被调用....");
}
public void add(){
System.out.println("add方法被调用....");
}
}
package com.jl.spring.service;
import com.jl.spring.dao.MemberDAOImpl;
/**
* @author long
* @date 2022/8/31
*/
public class MemberServiceImpl {
private MemberDAOImpl memberDAO;
public MemberDAOImpl getMemberDAO(){
return memberDAO;
}
public void setMemberDAO(MemberDAOImpl memberDAO) {
this.memberDAO = memberDAO;
}
public void add(){
System.out.println("MemberServiceImpl add() 被调用....");
memberDAO.add();
}
}
测试类
@Test
public void setBeanByRef(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
MemberServiceImpl memberService = ioc.getBean("memberService", MemberServiceImpl.class);
memberService.add();
}
<!--配置MemberDAOImpl对象-->
<bean class="com.jl.spring.dao.MemberDAOImpl" id="memberDAO"/>
<!--配置MemberServiceImpl对象-->
<bean class="com.jl.spring.service.MemberServiceImpl" id="memberService">
<property name="memberDAO" ref="memberDAO"/>
</bean>
property标签
中的name
和我们前边一样,都是属性的名称。但因为属性值是对象,所以我们这里使用rel
,rel
的值是引用的对象,而且这个值是引用的对象的id值。
这里说明的一点:我们没有要求必须要将引用对象的配置写到前边,因为Spring是在创建好对象之后才进行属性装配的。不知道我这里有没有说清楚,贴一张图吧:
最后的运行结果:
六、引用/注入内部bean对象
这里的内容和【五】一样都是属性为对象的时候的一种处理。但这里使用的是内部注入的方式。
类全部都一样,不同的就是配置方式的区别。
<!--使用内部bean的方式来配置MemberServiceImpl-->
<bean class="com.jl.spring.service.MemberServiceImpl" id="memberService">
<property name="memberDAO">
<bean class="com.jl.spring.dao.MemberDAOImpl"></bean>
</property>
</bean>
这种内部注入的方式,是在property 标签体
内,直接使用bean标签
来配置的。因为只是内部使用这个对象,所以可以只写个class
全类名就行。
七、引入/注入集合/数组类型
我们这里通过一个Master来讲解不同的集合类型。
package com.jl.spring.bean;
import java.util.*;
/**
* @author long
* @date 2022/8/31
*/
public class Master {
private String name;
private List<Monster> monsterList;
private Map<String,Monster> monsterMap;
private Set<Monster> monsterSet;
private String[] monsterName;
private Properties pros;
@Override
public String toString() {
return "Master{" +
"name='" + name + '\'' +
", monsterList=" + monsterList +
", monsterMap=" + monsterMap +
", monsterSet=" + monsterSet +
", monsterName=" + Arrays.toString(monsterName) +
", pros=" + pros +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Monster> getMonsterList() {
return monsterList;
}
public void setMonsterList(List<Monster> monsterList) {
this.monsterList = monsterList;
}
public Map<String, Monster> getMonsterMap() {
return monsterMap;
}
public void setMonsterMap(Map<String, Monster> monsterMap) {
this.monsterMap = monsterMap;
}
public Set<Monster> getMonsterSet() {
return monsterSet;
}
public void setMonsterSet(Set<Monster> monsterSet) {
this.monsterSet = monsterSet;
}
public String[] getMonsterName() {
return monsterName;
}
public void setMonsterName(String[] monsterName) {
this.monsterName = monsterName;
}
public Properties getPros() {
return pros;
}
public void setPros(Properties pros) {
this.pros = pros;
}
}
<!--配置Master对象,给集合属性赋值-->
<bean class="com.jl.spring.bean.Master" id="master">
<property name="name" value="太上老君"/>
<!--list集合-->
<property name="monsterList">
<list>
<!--引用的方式-->
<ref bean="monster01"/>
<ref bean="monster02"/>
<!--内部bean的方式-->
<bean class="com.jl.spring.bean.Monster">
<property name="name" value="葫芦娃"/>
<property name="skill" value="喷水"/>
<property name="monsterId" value="111"/>
</bean>
</list>
</property>
<!--map集合-->
<property name="monsterMap">
<map>
<entry>
<key>
<value>monster02</value>
</key>
<ref bean="monster02"></ref>
</entry>
<entry>
<key>
<value>monster03</value>
</key>
<ref bean="monster03"/>
</entry>
</map>
</property>
<!--set集合-->
<property name="monsterSet">
<set>
<ref bean="monster01"/>
<ref bean="monster02"/>
<bean class="com.jl.spring.bean.Monster">
<property name="monsterId" value="123"/>
<property name="name" value="银角大王"/>
<property name="skill" value="扔葫芦"/>
</bean>
</set>
</property>
<!--给数组注入-->
<property name="monsterName">
<array>
<value>123</value>
<value>321</value>
<value>456</value>
<value>654</value>
</array>
</property>
<!--配置properties-->
<property name="pros">
<props>
<prop key="key01">one</prop>
<prop key="key02">two</prop>
<prop key="key03">three</prop>
</props>
</property>
</bean>
这里面的Properties
是Hashtable
的子类 , 是 key-value 的形式(key和value都是String)。
测试类
@Test
public void setBeanByCollection(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master master = ioc.getBean("master", Master.class);
System.out.println(master);
}
结果截图
八、使用util名称空间
和p命名空间一样我们同样需要在XML文件的头部添加声明xmlns:util="http://www.springframework.org/schema/util"
我们这里同样使用Matser类说明。
<!--通过util命名空间配置-->
<util:list id="myList">
<ref bean="monster01"/>
<ref bean="monster02"/>
<ref bean="monster03"/>
</util:list>
<bean id="monster07" class="com.jl.spring.bean.Master">
<property name="monsterList" ref="myList"/>
</bean>
测试代码
@Test
public void setBeanByUtil(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master master = ioc.getBean("monster07", Master.class);
System.out.println(master);
}
运行截图
因为我们这里只注入了monsterList
属性,所以其他的属性都为null。当然util除了可以注入List,还可以注入其他的集合属性。
九、级联赋值
级联赋值,从他这个名字就可以看出:它是属性的多级关联赋值。不懂也没有关系,我们下边会举例说明。
首先我们的准备两个类:Dept
、Emp
package com.jl.spring.bean;
/**
* @author Long
* @date 2022/11/19
* @CSDN
**/
public class Emp {
private String name;
private Dept dept;
public Emp() {
}
public Emp(String name, Dept dept) {
this.name = name;
this.dept = dept;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", dept=" + dept +
'}';
}
}
package com.jl.spring.bean;
/**
* @author Long
* @date 2022/11/19
* @CSDN
**/
public class Dept {
private String name;
public Dept() {
}
public Dept(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
<bean id="emp" class="com.jl.spring.bean.Emp">
<property name="name" value="jack"/>
<property name="dept" ref="dept"/>
<property name="dept.name" value="Java 开发部"/>
</bean>
<bean id="dept" class="com.jl.spring.beans.Dept"/>
我们可以通过在引用对象之后给引用的对象的属性进行赋值。这样方式就叫级联赋值
。
测试类
@Test
public void setBeanByCascadingValues(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Emp emp = ioc.getBean("emp", Emp.class);
System.out.println(emp);
}
结果截图