V哥官网:http://www.vgxit.com
本博客对应视频教程:http://www.vgxit.com/course/23
Xml装配Bean
1,概述
通过之前的学习,大家已经熟练的掌握了SpringIOC和理念,并且对Spring依赖注入的使用有一个初步的了解。这里我们再来深入的学习一下Bean的装配。在Spring中提供了三种方式来对Bean进行配置:
- 在XML文件中配置
- 在Java的接口和实现类中配置
- 隐式Bean的发现机制和自动装配原则
在现实的工作中,这三种方式都会被用到,并且在学习和工作中常常混合使用。所以我们这三种方式都要学习。本节课我们先学习XML装配Bean。
2,分析bean标签
<bean id="person" class="com.vgxit.spring.ktdm.vgioc.beans.Person">
<property name="id" value="1"/>
<property name="name" value="V哥"/>
<property name="nickName" value="V哥学IT"/>
</bean>
1,bean标签有一个id属性,这个id属性就是为bean取一个全局唯一的名字。这个属性不是一个必须的属性,如果没有申明它,那么Spring会采用"全限定名#{number}"的方式来自动为我们生成一个编号,number从0开始计数。比如我们申明了两个Person对象,如下:
<bean class="com.vgxit.spring.ktdm.vgioc.beans.Person">
<property name="id" value="1"/>
<property name="name" value="V哥"/>
<property name="nickName" value="V哥学IT"/>
</bean>
<bean class="com.vgxit.spring.ktdm.vgioc.beans.Person">
<property name="id" value="2"/>
<property name="name" value="李一桐"/>
<property name="nickName" value="桐桐"/>
</bean>
这个时候,如果我们再用原来的方式获取Person对象就获取不到了,因为我们的id是Spring自动生成的,我们并没有指定。
package com.vgxit.spring.ktdm.vgioc.test;
import com.vgxit.spring.ktdm.vgioc.beans.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Ioc001Test {
public static void main(String[] args) {
//1,首先通过配置文件获取到Spring的上下文
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
//2,获取对应的对象
Person person = (Person) ctx.getBean(Person.class.getName() + "#0");
//调用方法
person.sayHello("周杰伦");
}
}
2,class就是我们要注入的对象的类型,这里填写一个类的全限定名
3,property元素定义类的属性,其中name表示属性名,value表示属性值
3,装配集合
我们之前讲了通过property标签的方式来实现注入。但是这个对于一些基本数据类型和String类型的注入还是比较方便的。但是如果我们的类型是集合类型(List, Set, Map, Properties)怎么办?
1,接下来我们就定义一个新的类来做:
package com.vgxit.spring.ktdm.vgioc.beans;
import lombok.Data;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@Data
public class Coder {
private String name;
private List<String> languages;
private Set<String> friends;
private Map<String, Integer> houses;
private Properties properties;
}
2,在spring的xml文件中,注入Coder:
<bean id="coder" class="com.vgxit.spring.ktdm.vgioc.beans.Coder">
<property name="name" value="V哥"/>
<property name="languages">
<!--配置list集合-->
<list>
<value>java</value>
<value>php</value>
<value>sql</value>
<value>shell</value>
<value>javascript</value>
</list>
</property>
<property name="friends">
<!--配置set集合-->
<set>
<value>李一桐</value>
<value>鞠婧祎</value>
<value>郑爽</value>
<value>迪丽热巴</value>
</set>
</property>
<property name="houses">
<!--配置map集合-->
<map>
<entry key="汤臣一品" value="30000000"/>
<entry key="中国铁建" value="24000000"/>
</map>
</property>
<property name="properties">
<!--配置properties集合-->
<props>
<prop key="height">178</prop>
<prop key="weight">140</prop>
<prop key="age">18</prop>
</props>
</property>
</bean>
3,调用测试:
private static void testCoder() {
//1,首先通过配置文件获取到Spring的上下文
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
Coder coder = (Coder) ctx.getBean("coder");
System.out.println(coder);
}
4,复杂Bean装配
上面我们讲了一下使用XML的方式如何装配集合。但是,我们想想如果我们的属性是一个复杂集合对象怎么办呢?比如,我们的属性是List或者Set,而这个List的泛型是一个对象。比如我们的Map,key和value都是一个对象怎么办?
解决思路,我们先把对应的bean注入好,然后在我们注入属性的时候引入过来就行。
1,我们定义三个类,分别是用户,角色,还有一个是用户角色关联。
@Data
public class User {
private Integer id;
private String name;
}
@Data
public class Role {
private Integer id;
private String name;
}
@Data
public class UserRole {
private Integer id;
private List<User> users;
private Map<Role, User> map;
}
2,注入的思路,首先我们先把依赖的对象给注入了,然后再来注入自己。
<bean id="user1" class="com.vgxit.spring.ktdm.vgioc.beans.User">
<property name="id" value="1"/>
<property name="name" value="V哥"/>
</bean>
<bean id="user2" class="com.vgxit.spring.ktdm.vgioc.beans.User">
<property name="id" value="2"/>
<property name="name" value="李一桐"/>
</bean>
<bean id="role1" class="com.vgxit.spring.ktdm.vgioc.beans.Role">
<property name="id" value="1"/>
<property name="name" value="超级管理员"/>
</bean>
<bean id="role2" class="com.vgxit.spring.ktdm.vgioc.beans.Role">
<property name="id" value="2"/>
<property name="name" value="普通用户"/>
</bean>
<bean id="userRole" class="com.vgxit.spring.ktdm.vgioc.beans.UserRole">
<property name="id" value="1"/>
<property name="users">
<list>
<ref bean="user1"/>
<ref bean="user2"/>
</list>
</property>
<property name="map">
<map>
<entry key-ref="role1" value-ref="user1"/>
<entry key-ref="role2" value-ref="user2"/>
</map>
</property>
</bean>
3,创建对象,打印效果:
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-ioc-cfg.xml");
Coder coder = (Coder) ctx.getBean("coder");
System.out.println(coder);
5,命名空间装配(了解)
命名空间装配在写法上比我们上面的控制器装配和setter装配要简单。但是这种写法可读性不好,基本上在工作中没人这么用。但是Spring的确是提供了这样的功能,这里老师也给大家介绍一下。
1,使用构造方法装配
这里我们还是使用之前我们用过的Person类来做实验:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Integer id;
private String name;
private String nickName;
public void sayHello(String name) {
System.out.println(this.name + "[" + this.nickName + "] Hello " + name);
}
}
然后,我们创建一个新的spring配置文件spring-namespace.xml引入通过构造方法以命名空间方式注入的XSD文件,然后注入:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.vgxit.learn.bean.bk.beans.Person" c:_0="1" c:_1="V哥" c:_2="V哥学IT"/>
</beans>
2,使用setter方法装配
这里我们还是使用之前我们用过的Person类来做实验:
1,注入代码如下
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person2" class="com.vgxit.learn.bean.bk.beans.Person" p:id="1" p:name="李一桐" p:nickName="tongtong"/>
</beans>
3,命名空间的方式注入复杂Bean
package com.vgxit.learn.bean.bk.beans;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class UserRole {
private Integer id;
//新加的
private List<String> names;
private List<User> users;
private Map<Role, User> map;
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<util:list id="names">
<value>java</value>
<value>php</value>
<value>javascript</value>
<value>golang</value>
</util:list>
<util:list id="users">
<ref bean="user1"/>
<ref bean="user2"/>
</util:list>
<util:map id="map">
<entry key-ref="role1" value-ref="user1"/>
<entry key-ref="role2" value-ref="user2"/>
</util:map>
<bean id="userRole" class="com.vgxit.learn.bean.bk.beans.UserRole" p:id="1" p:names-ref="names" p:users-ref="users" p:map-ref="map"/>
</beans>