目录
1、set注入之外部注入和内部注入
public class VipDao {
private static final Logger logger = LoggerFactory.getLogger(VipDao.class);
public void insert(){
logger.info("正在保存VIP用户信息。");
}
}
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void saveUser(){
userDao.insert();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--使用ref属性来引入,这就是注入外部bean-->
<bean id="vipDaoBean" class="com.ray.dao.VipDao"></bean>
<bean id="vipServiceBean" class="com.ray.service.VipService">
<property name="vipDao" ref="vipDaoBean"></property>
</bean>
<!--Bean里面写个Bean,就是注入内部bean-->
<bean id="vipServiceBean2" class="com.ray.service.VipService">
<property name="vipDao">
<bean id="vipDaoBean2" class="com.ray.dao.VipDao"></bean>
</property>
</bean>
</beans>
public class DITest {
@Test
public void testSetDI3(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("setDI.xml");
VipService vipServiceBean2 = applicationContext.getBean("vipServiceBean2", VipService.class);
vipServiceBean2.insert();
}
@Test
public void testSetDI2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("setDI.xml");
VipService vipServiceBean = applicationContext.getBean("vipServiceBean", VipService.class);
vipServiceBean.insert();
}
}
实现效果:
2、简单注入
public class User {
private String userName;
private String password;
private int age;
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--简单类型-->
<!--如果像这种string、int类型的属性,我们称为简单类型,这种简单类型在注入的时候要使用value属性,不能使用ref-->
<bean id="userBean" class="com.ray.bean.User">
<property name="age" value="18"></property>
<property name="password" value="123456"></property>
<property name="userName" value="阿奇"></property>
</bean>
</beans>
public class DITest {
@Test
public void testSimpleDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("setDI.xml");
User userBean = applicationContext.getBean("userBean", User.class);
System.out.println(userBean);
}
}
实现效果:
简单类型总结:
//源码
public static boolean isSimpleValueType(Class<?> type) {
return Void.class != type && Void.TYPE != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type);
}
这段代码是一个静态方法 isSimpleValueType
的实现,用于判断一个类型是否为简单类型。以下是对代码中使用的条件进行解释的简介:
Void.class != type && void.class != type
: 排除Void
类型和void
类型。
ClassUtils.isPrimitiveOrWrapper(type)
: 使用ClassUtils
工具类的isPrimitiveOrWrapper
方法判断类型是否为原始类型或其包装类。
Enum.class.isAssignableFrom(type)
: 判断类型是否为枚举类型。
CharSequence.class.isAssignableFrom(type)
: 判断类型是否为CharSequence
的子类,即字符串类型。
Number.class.isAssignableFrom(type)
: 判断类型是否为Number
的子类,即数值类型。
Date.class.isAssignableFrom(type)
: 判断类型是否为Date
类型。
Temporal.class.isAssignableFrom(type)
: 判断类型是否为Temporal
的子类,用于表示时间。
URI.class == type
: 判断类型是否为URI
类型。
URL.class == type
: 判断类型是否为URL
类型。
Locale.class == type
: 判断类型是否为Locale
类型。
Class.class == type
: 判断类型是否为Class
类型。
以上条件组合在一起,用于判断给定类型是否属于简单类型。如果类型满足其中任何一个条件,则被认为是简单类型,返回 true
;否则,被认为是复杂类型,返回 false
。
注意:在实际开发中,我们一般不会把Date类型当做简单类型,虽然它是简单类型。一般采用ref给Date类型的属性赋值。若是使用value也可以,但是要有固定的格式。
<property name="nowDate" value="Wed Jun 07 14:14:37 CST 2023"></property>
实现效果:
简单类型通常是指基本类型、字符串类型、数值类型、日期类型、枚举类型以及一些常用的特殊类型(如 URI
、URL
、Locale
、Class
等)。这个方法的目的是提供一种便捷的方式来判断一个类型是否属于简单类型,以便在需要处理简单类型的场景中进行相应的操作。
3、级联属性(了解)
public class Clazz {
private String className;
public void setClassName(String className) {
this.className = className;
}
@Override
public String toString() {
return "Clazz{" +
"className='" + className + '\'' +
'}';
}
}
public class Student {
private String studentName;
private Clazz clazz;
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@Override
public String toString() {
return "Student{" +
"studentName='" + studentName + '\'' +
", clazz=" + clazz +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
注意:
1、顺序不能颠倒,不能先级联属性赋值,再<property name="clazz" ref="clazzBean"></property>
2、clazz属性必须要提供getter方法
-->
<bean id="studentBean" class="com.ray.bean.Student">
<property name="studentName" value="阿奇"></property>
<!--z这不是简单类型,使用ref-->
<property name="clazz" ref="clazzBean"></property>
<!--级联属性赋值-->
<property name="clazz.className" value="计算机二班"></property>
</bean>
<bean id="clazzBean" class="com.ray.bean.Clazz"></bean>
</beans>
@Test
public void testCascadeDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("cascade.xml");
Student studentBean = applicationContext.getBean("studentBean", Student.class);
System.out.println(studentBean);
}
实现效果:
4、注入数组(简单类型数组和非简单类型数组)
public class MyHobby {
private String[] hobbies;
private Play[] plays;
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
public void setPlays(Play[] plays) {
this.plays = plays;
}
@Override
public String toString() {
return "MyHobby{" +
"hobbies=" + Arrays.toString(hobbies) +
", plays=" + Arrays.toString(plays) +
'}';
}
}
public class Play {
private String playName;
public void setPlayName(String playName) {
this.playName = playName;
}
@Override
public String toString() {
return "Play{" +
"playName='" + playName + '\'' +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="playBean1" class="com.ray.bean.Play">
<property name="playName" value="吉他"></property>
</bean>
<bean id="playBean2" class="com.ray.bean.Play">
<property name="playName" value="游戏"></property>
</bean>
<bean id="playBean3" class="com.ray.bean.Play">
<property name="playName" value="碰碰车"></property>
</bean>
<bean id="myHobbyBean" class="com.ray.bean.MyHobby">
<!--这个数组属性当中的元素类型是String简单类型-->
<property name="hobbies">
<array>
<value>吃</value>
<value>乐</value>
<value>玩</value>
<value>乐</value>
</array>
</property>
<!--这个数组当中的类型是自定义的Play类型,不是简单类型-->
<property name="plays">
<array>
<ref bean="playBean1"></ref>
<ref bean="playBean2"></ref>
<ref bean="playBean3"></ref>
</array>
</property>
</bean>
</beans>
@Test
public void testArrayDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("array.xml");
MyHobby myHobbyBean = applicationContext.getBean("myHobbyBean", MyHobby.class);
System.out.println(myHobbyBean);
}
实现效果:
5、注入list集合和set集合
public class Person {
private List<String> names;
private Set<String> address;
public void setNames(List<String> names) {
this.names = names;
}
public void setAddress(Set<String> address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"names=" + names +
", address=" + address +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="personBean" class="com.ray.bean.Person">
<property name="names">
<!--list集合:有序可重复-->
<list>
<value>阿奇</value>
<value>阿奇</value>
<value>毛毛</value>
<value>汤姆</value>
<value>杰克</value>
<value>阿奇</value>
</list>
</property>
<property name="address">
<!--set集合:无序,不可重复-->
<set>
<value>北京海淀区</value>
<value>北京海淀区</value>
<value>北京朝阳区</value>
</set>
</property>
</bean>
</beans>
@Test
public void testCollectionDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("collection.xml");
Person person = applicationContext.getBean("personBean", Person.class);
System.out.println(person);
}
实现效果:
6、注入map集合和properties集合
public class Person {
private Map phone;
/*
* 注入属性类对象
* Properties本质上也是一个Map集合
* Properties的父类Hashtable,Hashtable实现了Map接口。
* 虽然这个也是一个Map集合,但是和Map的注入方式有点像,但是不同。
* Properties的key和value只能是String类型。
* */
private Properties properties;
public void setPhone(Map phone) {
this.phone = phone;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "Person{" +
"phone=" + phone +
", properties=" + properties +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="personBean" class="com.ray.bean.Person">
<property name="phone">
<map>
<!--如果key不是简单类型,使用 key-ref 属性-->
<!--如果value不是简单类型,使用 value-ref 属性-->
<entry key="0" value="110"></entry>
<entry key="1" value="112"></entry>
<entry key="2" value="114"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="address">com.ray.bean</prop>
<prop key="userName">root</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
</beans>
@Test
public void testCollectionDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("collection.xml");
Person person = applicationContext.getBean("personBean", Person.class);
System.out.println(person);
}
实现效果:
7、注入null和空字符串
public class Cat {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<bean id="catBean" class="com.ray.bean.Cat">
<!--不给属性赋值,则属性的默认值就是null-->
<!--<property name="name" value="tom"></property>-->
<!--这不是注入null,这是注入了一个‘null’字符串-->
<!--<property name="name" value="null"></property>-->
<!--这种方式是手动注入null-->
<!--<property name="name"><null/></property>-->
<!--注入空字符串的第一种方式-->
<!--<property name="name" value=""></property>-->
<!--注入空字符串的第一种方式-->
<!--<property name="name"><value/></property>-->
<property name="age" value="15"></property>
</bean>
8、注入的值中含有特殊符号
在XML中有5个特殊字符,分别是:<、>、'、"、&
以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。
因此当使用set注入的值含有特殊符号时,解决方案包括两种:
- 第一种:特殊符号使用转义字符代替。
- 第二种:将含有特殊符号的字符串放到:<![CDATA[]]> 当中。因为放在CDATA区中的数据不会被XML文件解析器解析。
5个特殊字符对应的转义字符分别是(截图来自动力字节):
public class Cat {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<!--第一种方式:使用实体符号代替特殊符号-->
<property name="name" value="7 > 4">
</property>
<!--第二种方案:使用<![CDATA[]]> 这里注意'<>'不要忘记添加-->
<!--<property name="name">-->
<!--只能使用value标签,不能使用value属性,即property name="name" value="<![CDATA[7 > 4]]>"-->
<!-- <value><![CDATA[7 > 4]]></value>-->
<!--</property>-->
<property name="age" value="15"></property>
@Test
public void testMathDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("collection.xml");
Cat catBean = applicationContext.getBean("catBean", Cat.class);
System.out.println(catBean);
}
实现效果:
9、P命名空间注入(简化set注入)
public class Cat {
//简单数据类型
private String name;
private int age;
//Date虽然是简单类型,但是我们通常都是作为非简单类型
private Date date;
public void setDate(Date date) {
this.date = date;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--第一步:在XML头部信息中添加p命名空间的配置信息:xmlns:p="http://www.springframework.org/schema/p"-->
<!-- 第二步:使用p:属性名 = “属性值”-->
<bean id="catBean" class="com.ray.bean.Cat" p:name="小砾" p:age="3" p:date-ref="dateBean"></bean>
<bean id="dateBean" class="java.util.Date"></bean>
</beans>
@Test
public void testPDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("p.xml");
Cat catBean = applicationContext.getBean("catBean", Cat.class);
System.out.println(catBean);
}
10、基于xml的自动装配
示例1(根据名称自动装配):
public class UserDao {
private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
public void insert(){
// 使用log4j2 日志框架
logger.info("数据库正在保存用户信息。");
}
}
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void saveUser(){
userDao.insert();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--根据名字自动装配-->
<bean id="userBean" class="com.ray.service.UserService" autowire="byName"></bean>
<bean id="userDao" class="com.ray.dao.UserDao"></bean>
<!--正常的注入模式,ref是可以随便命名的,只要上下保持一致即可-->
<!--<bean id="userBean" class="com.ray.service.UserService">-->
<!-- <property name="userDao" ref="aaaa"></property>-->
<!--</bean>-->
<!--<bean id="aaaa" class="com.ray.dao.UserDao"></bean>-->
</beans>
@Test
public void testAutowireDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("autowire.xml");
UserService userBean = applicationContext.getBean("userBean", UserService.class);
userBean.saveUser();
}
实现效果:
示例2(根据类型自动装配):
public class UserDao {
private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
public void insert(){
// 使用log4j2 日志框架
logger.info("数据库正在保存用户信息。");
}
}
public class VipDao {
private static final Logger logger = LoggerFactory.getLogger(VipDao.class);
public void insert(){
logger.info("正在保存VIP用户信息。");
}
}
public class CustomerService {
private UserDao userDao;
private VipDao vipDao;
// 根据构造参数进行注入
/* public CustomerService(UserDao userDao, VipDao vipDao) {
this.userDao = userDao;
this.vipDao = vipDao;
}*/
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setVipDao(VipDao vipDao) {
this.vipDao = vipDao;
}
public void save(){
userDao.insert();
vipDao.insert();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--根据类型自动装配-->
<bean class="com.ray.dao.UserDao"></bean>
<bean class="com.ray.dao.VipDao"></bean>
<bean id="cs" class="com.ray.service.CustomerService" autowire="byType"></bean>
<!--根据名字自动装配-->
<!--<bean id="userBean" class="com.ray.service.UserService" autowire="byName"></bean>-->
<!--<bean id="userDao" class="com.ray.dao.UserDao"></bean>-->
<!--正常的注入模式,ref是可以随便命名的,只要上下保持一致即可-->
<!--<bean id="userBean" class="com.ray.service.UserService">-->
<!-- <property name="userDao" ref="aaaa"></property>-->
<!--</bean>-->
<!--<bean id="aaaa" class="com.ray.dao.UserDao"></bean>-->
</beans>
@Test
public void testAutowireDI2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("autowire.xml");
CustomerService customerService = applicationContext.getBean("cs", CustomerService.class);
customerService.save();
}
实现效果: