Spring6| Spring对IoC的实现(核心重点)
Posted @每天都要敲代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring6| Spring对IoC的实现(核心重点)相关的知识,希望对你有一定的参考价值。
目录
7. 基于XML的自动装配(byName & byType)
8. Spring引入外部属性配置文件(使用context命名空间)
一:Spring对IoC的实现
前面我们已经学会了如何用spring创建管理对象,接下来就要学习如何让对象和对象产生关系,使用依赖注入!
1. IoC 控制反转
(1)控制反转是一种思想,一种新型的设计模式!
(2)控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则。
(3)控制反转,反转的是什么?
①将对象的创建权利交出去,交给第三方容器负责。
②将对象和对象之间关系的维护权交出去,交给第三方容器负责。
(4)控制反转这种思想如何实现呢?
DI(Dependency Injection):依赖注入
2. 依赖注入
依赖注入实现了控制反转的思想!
Spring通过依赖注入的方式来完成Bean管理的。Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。
依赖注入:
- 依赖指的是对象和对象之间的关联关系。
- 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
依赖注入常见的实现方式包括两种:
- 第一种:set注入
- 第二种:构造注入
2.1 set注入
set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值;这种方式要求属性必须对外提供set方法!
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjpowernode</groupId>
<artifactId>spring6-002-dependency-injection</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!--配置多个仓库-->
<repositories>
<!--spring6里程碑的仓库-->
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<dependencies>
<!--spring context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.0-M2</version>
</dependency>
<!--单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--log4j2的依赖-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.19.0</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
log4j2.xml日志配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<loggers>
<root level="DEBUG">
<appender-ref ref="spring6log"/>
</root>
</loggers>
<appenders>
<console name="spring6log" target="SYSTEM_OUT">
<PatternLayout pattern="%dyyyy-MM-dd HH:mm:ss SSS [%t] %-3level %logger1024 - %msg%n"/>
</console>
</appenders>
</configuration>
UserDao类:连接数据库的操作
package com.bjpowernode.spring6.dao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserDao
// 一般声明为常量
private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
// 使用日志进行打印,用System.out.println也可以
public void insert()
logger.info("数据库正在保存用户信息!");
UserService类:调用UserDao中的方法
①set注入的话,必须提供一个set方法;Spring容器会调用这个set方法,来给userDao属性赋值。
②这个set方法不符合javabean规范也可以,但是必须以set开头,例如:setUD也是可以的;这里我使用的是IDEA自动生成的符合javabean规范的。
package com.bjpowernode.spring6.service;
import com.bjpowernode.spring6.dao.UserDao;
public class UserService
private UserDao userDao;
// set注入,必须提供一个set方法
public void setUserDao(UserDao userDao)
this.userDao = userDao;
public void saveUser()
// 调用UserDao保存用户信息
userDao.insert();
spring.xml配置
①配置userDaoBean和UserService,让spring管理这两个类。
②对于UserService,想让Spring调用对应的set方法,需要配置property标签:
name属性值:set方法的方法名,去掉set,然后把剩下的单词首字母变小写
ref属性值:翻译为引用,英语单词references,后面指定的是要注入的bean的id
<?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: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 https://www.springframework.org/schema/util/spring-util.xsd">
<!--配置dao-->
<bean id="userDaoBean" class="com.bjpowernode.spring6.dao.UserDao"/>
<!--配置service-->
<bean id="userServiceBean" class="com.bjpowernode.spring6.service.UserService">
<property name="userDao" ref="userDaoBean" />
</bean>
</beans>
③另外,对于property标签来说,ref属性也可以采用标签的方式,但使用ref属性是多数的:
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
<property name="userDao">
<ref bean="userDaoBean"/>
</property>
</bean>
编写测试类
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DITest
@Test
public void testSetDI()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userServiceBean = applicationContext.getBean("userServiceBean", UserService.class);
userServiceBean.saveUser();
执行结果:
正常输出日志信息了,说明两个问题:
①spring正常创建UserDao和UserService对象了!
②spring关联了对象与对象之间的关系了!
总结:set注入的核心实现原理是通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系。
2.2 构造注入
核心原理:通过调用构造方法来给属性赋值。
①set注入:是先创建对象,才能执行set方法,给属性赋值。
②构造注入:是在创建对象的同时,给属性赋值,时机是不同的。
在定义一个VipDao类
package com.bjpowernode.spring6.dao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VipDao
private static final Logger logger = LoggerFactory.getLogger(VipDao.class);
public void delete()
logger.info("正在删除信息!");
ConstructService类
构造方法注入,必须要提供一个构造方法!
package com.bjpowernode.spring6.service;
import com.bjpowernode.spring6.dao.UserDao;
import com.bjpowernode.spring6.dao.VipDao;
public class ConstructService
private UserDao userDao;
private VipDao vipDao;
// 构造注入,必须有构造方法
public ConstructService(UserDao userDao, VipDao vipDao)
this.userDao = userDao;
this.vipDao = vipDao;
public void save()
userDao.insert();
vipDao.delete();
bean.xml配置
访问的方式有三种:使用的是constructor-arg标签
①第一种方式是根据下标index的方式,下标的顺序是构造方法参数的顺序。
②第二种方式是根据构造方法参数的名字name的方式。
③第三种方式是根据类型进行注入,不指定,spring会自己推断做类型匹配。
<?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="userDaoBean" class="com.bjpowernode.spring6.dao.UserDao"/>
<bean id="vipDaoBean" class="com.bjpowernode.spring6.dao.VipDao"/>
<bean id="constructServiceBean" class="com.bjpowernode.spring6.service.ConstructService">
<!--第一种方式-->
<constructor-arg index="0" ref="userDaoBean"/>
<constructor-arg index="1" ref="vipDaoBean" />
<!--第二种方式-->
<constructor-arg name="userDao" ref="userDaoBean"/>
<constructor-arg name="vipDao" ref="vipDaoBean"/>
<!--第三种方式-->
<constructor-arg ref="userDaoBean"/>
<constructor-arg ref="vipDaoBean" />
</bean>
</beans>
编写测试
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.service.ConstructService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ConstructTest
@Test
public void testConstructDI()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
ConstructService constructServiceBean = applicationContext.getBean("constructServiceBean", ConstructService.class);
constructServiceBean.save();
执行结果:
3. set注入专题
set注入和构造注入中,set注入用的比较多,所以下面就学习一下set注入的专题!
3.1 注入外部Bean
(1)在之前我们使用的案例一直就是注入外部Bean的方式!
(2)外部Bean的特点:bean定义到外面,在property标签中使用ref属性进行注入;通常这种方式是常用!
<?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: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 https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="userDaoBean" class="com.bjpowernode.spring6.dao.UserDao"/>
<bean id="userServiceBean" class="com.bjpowernode.spring6.service.UserService">
<property name="userDao" ref="userDaoBean" />
</bean>
</beans>
3.2 注入内部Bean
内部Bean的方式:在bean标签中直接嵌套bean标签,不需要ref属性引入。
<?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: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 https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="userServiceBean" class="com.bjpowernode.spring6.service.UserService">
<property name="userDao">
<bean class="com.bjpowernode.spring6.dao.UserDao"/>
</property>
</bean>
</beans>
3.3 注入简单类型
(1)之前在进行注入的时候,对象的属性都是另一个对象;那如果对象的属性是int类型呢?也可以通过set注入的方式给该属性赋值,实际上只要能够调用set方法就可以给属性赋值。
(2)重点:如果给简单类型赋值,就不能使用ref属性,需要使用value属性!
User类:定义了两个简单类型,写上set方法
package com.bjpowernode.spring6.bean;
public class User
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 "User" +
"name='" + name + '\\'' +
", age=" + age +
'';
set-di.xm配置
注:既可以使用value标签的方式,也可以使用value属性的方式(常用)
<?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.bjpowernode.spring6.bean.User">
<property name="age" value="18"/>
<property name="name" value="张三"/>
</bean>
</beans>
编写测试
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.bean.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetDITest
@Test
public void testSimpleTypeSet()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");
User user = applicationContext.getBean("userBean", User.class);
System.out.println(user);
执行结果:默认会调用toString方法
需要特别注意:如果给简单类型赋值,使用value属性或value标签,而不是ref!
(3)那么简单类型包括哪些呢?可以通过Spring的源码来分析一下!
双击shift搜索BeanUtils类,ctrl+F12搜索isSimpleValueType方法,里面都是简单类型:
(4)这里重点说一下Date类型,如果硬要把Date类型当做简单类型,使用value赋值的话,这个日期的格式有要求:Thu Jan 12 21:05:49 CST 2023 ,所以在实际的开发中,我们一般采用ref属性的方式给Date类型的属性赋值!
(5)简单类型注入的经典案例:给数据源的属性注入值:
假设我们现在要自己手写一个数据源(能够提供Connection对象的),我们都知道所有的数据源都要实现javax.sql.DataSource接口,并且数据源中应该有连接数据库的信息,例如:driver、url、username、password等。
数据源MyDataSource
package com.bjpowernode.spring6.jdbc;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
public class MyDateSource implements DataSource
private String driver;
private String url;
private String username;
private String password;
public void setDriver(String driver)
this.driver = driver;
public void setUrl(String url)
this.url = url;
public void setUsername(String username)
this.username = username;
public void setPassword(String password)
this.password = password;
@Override
public String toString()
return "MyDateSource" +
"driver='" + driver + '\\'' +
", url='" + url + '\\'' +
", username='" + username + '\\'' +
", password='" + password + '\\'' +
'';
@Override
public Connection getConnection() throws SQLException
return null;
@Override
public Connection getConnection(String username, String password) throws SQLException
return null;
@Override
public PrintWriter getLogWriter() throws SQLException
return null;
@Override
public void setLogWriter(PrintWriter out) throws SQLException
@Override
public void setLoginTimeout(int seconds) throws SQLException
@Override
public int getLoginTimeout() throws SQLException
return 0;
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException
return null;
@Override
public <T> T unwrap(Class<T> iface) throws SQLException
return null;
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
return false;
spring-datasource.xml:使用spring的依赖注入完成数据源对象的创建和属性的赋值
<?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 name="myDataSource" class="com.bjpowernode.spring6.jdbc.MyDateSource">
<property name="driver" value="com.mysql.jdbc.driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring6"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
</beans>
编写测试
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.bean.User;
import com.bjpowernode.spring6.jdbc.MyDateSource;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetDITest
@Test
public void testMyDataSource()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-datasource.xml");
MyDateSource myDataSource = applicationContext.getBean("myDataSource", MyDateSource.class);
System.out.println(myDataSource);
测试结果:成功注入连接数据库的信息
3.4 级联属性赋值(了解)
我们先回顾一下原来使用的注入方式,然后在使用级联属性赋值,进行对比!
clazz班级类
package com.bjpowernode.spring6.bean;
public class Clazz
// 班级名称
private String name;
public void setName(String name)
this.name = name;
@Override
public String toString()
return "Clazz" +
"name='" + name + '\\'' +
'';
Student学生类
package com.bjpowernode.spring6.bean;
public class Student
// 学生姓名
private String name;
// 班级
private Clazz clazz;
public void setName(String name)
this.name = name;
public void setClazz(Clazz clazz)
this.clazz = clazz;
@Override
public String toString()
return "Student" +
"name='" + name + '\\'' +
", 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">
<bean name="clazzBean" class="com.bjpowernode.spring6.bean.Clazz">
<property name="name" value="高三一班"/>
</bean>
<bean name="studentBean" class="com.bjpowernode.spring6.bean.Student">
<property name="name" value="张三"/>
<property name="clazz" ref="clazzBean"/>
</bean>
</beans>
第二种方式:级联注入方式
使用级联属性赋值需要注意两点:
①配置的顺序不能颠倒,先配置student在配置clazz
②clazz属性必须提供getClazz()方法(所以要在Student类当中要增加getter方法)
<?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 name="studentBean" class="com.bjpowernode.spring6.bean.Student">
<property name="name" value="张三"/>
<property name="clazz" ref="clazzBean"/>
<!--级联属性赋值-->
<property name="clazz.name" value="高三一班"/>
</bean>
<bean name="clazzBean" class="com.bjpowernode.spring6.bean.Clazz" />
</beans>
执行结果:
3.5 注入数组
这里主要学习两种情况:数组中的元素是简单类型和当数组中的元素是非简单类型!
Woman类,作为非简单类型
package com.bjpowernode.spring6.bean;
public class Woman
private String name;
@Override
public String toString()
return "Woman" +
"name='" + name + '\\'' +
'';
public void setName(String name)
this.name = name;
QY类,里面包含简单类型和非简单类型的数组属性
package com.bjpowernode.spring6.bean;
import java.util.Arrays;
public class QY
// 简单类型的数组
private String[] loves;
// 非简单类型的数组
private Woman[] women;
@Override
public String toString()
return "QY" +
"loves=" + Arrays.toString(loves) +
", women=" + Arrays.toString(women) +
'';
public void setLoves(String[] loves)
this.loves = loves;
public void setWomen(Woman[] women)
this.women = women;
spring-array.xml配置
当属性是数组时,需要先使用一下array标签,在array标签中再写value和ref标签进行赋值!
<?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="w1" class="com.bjpowernode.spring6.bean.Woman">
<property name="name" value="小花"/>
</bean>
<bean id="w2" class="com.bjpowernode.spring6.bean.Woman">
<property name="name" value="小红"/>
</bean>
<!--简单类型-->
<bean id="yqBean" class="com.bjpowernode.spring6.bean.QY">
<!-- 注入简单类型-->
<property name="loves">
<array>
<value>抽烟</value>
<value>喝酒</value>
<value>烫头</value>
</array>
</property>
<!--注入非简单类型-->
<property name="women" >
<array>
<ref bean="w1"/>
<ref bean="w2"/>
</array>
</property>
</bean>
</beans>
编写测试
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.bean.Clazz;
import com.bjpowernode.spring6.bean.QY;
import com.bjpowernode.spring6.bean.Student;
import com.bjpowernode.spring6.bean.User;
import com.bjpowernode.spring6.jdbc.MyDateSource;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetDITest
@Test
public void testArraySet()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-array.xml");
QY yqBean = applicationContext.getBean("yqBean", QY.class);
System.out.println(yqBean);
执行结果:
要点:
如果数组中是简单类型,使用value标签。
如果数组中是非简单类型,使用ref标签。
3.6 注入List集合和Set集合
Person类
package com.bjpowernode.spring6.bean;
import java.util.List;
import java.util.Set;
public class Person
// 注入List
private List<String> names;
// 注入Set集合
private Set<String> addrs;
@Override
public String toString()
return "Person" +
"names=" + names +
", addrs=" + addrs +
'';
public void setNames(List<String> names)
this.names = names;
public void setAddrs(Set<String> addrs)
this.addrs = addrs;
spring-collection.xml配置
如果是List集合或者Set集合的属性,需要先使用<list>标签和<set>标签,标签中再写value和ref标签进行赋值!
<?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.bjpowernode.spring6.bean.Person">
<!--List集合-->
<property name="names">
<list>
<value>张三</value>
<value>李四</value>
<value>张三</value>
<value>王五</value>
</list>
</property>
<!--Set集合-->
<property name="addrs">
<set>
<value>张三</value>
<value>李四</value>
<value>张三</value>
<value>王五</value>
</set>
</property>
</bean>
</beans>
编写测试
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.bean.*;
import com.bjpowernode.spring6.jdbc.MyDateSource;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetDITest
@Test
public void testCollectionSet()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-collection.xml");
Person personBean = applicationContext.getBean("personBean", Person.class);
System.out.println(personBean);
执行结果:
从执行结果上看,可以得出:List集合是有序可重复、Set集合是无序不可重复!
注意:注入List集合的时候使用list标签,注入Set集合的时候使用set标签,如果集合中是简单类型使用value标签,反之使用ref标签。
3.7 注入Map和Properties集合
Properties集合本质上也是一个Map集合,但是Properties集合的key和value只能是String类型,并且注入的方式也是与Map集合不同的!
Man类
package com.bjpowernode.spring6.bean;
import java.util.Map;
import java.util.Properties;
public class Man
// 注入Map集合
private Map<String,Integer> phones;
// 注入Properties
private Properties properties;
@Override
public String toString()
return "Man" +
"phones=" + phones +
", properties=" + properties +
'';
public void setProperties(Properties properties)
this.properties = properties;
public void setPhones(Map<String, Integer> phones)
this.phones = phones;
spring-collection.xml配置
如果是Map集合的属性,使用map标签嵌套entry子标签(不使用ref和value标签了)
如果是Map集合的属性,使用props标签嵌套pro标签
<?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="manBean" class="com.bjpowernode.spring6.bean.Man">
<!--Map集合-->
<property name="phones">
<map>
<entry key="张三" value="123"/>
<entry key="李四" value="456"/>
<entry key="王五" value="789"/>
</map>
</property>
<!-- Properties集合-->
<property name="properties">
<props>
<prop key="driver">com.mysql.jdbc.driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring6</prop>
</props>
</property>
</bean>
</beans>
执行结果:
要点:
对于Map集合使用<map>标签,对于Properties使用<props>标签嵌套<prop>标签完成。
如果key是简单类型,使用 key 属性,反之使用 key-ref 属性。
如果value是简单类型,使用 value 属性,反之使用 value-ref 属性。
3.8 注入null和空字符串
Cat类
package com.bjpowernode.spring6.bean;
public class Cat
private String name;
private int age;
@Override
public String toString()
return "Cat" +
"name='" + name + '\\'' +
", age=" + age +
'';
public void setName(String name)
this.name = name;
public void setAge(int age)
this.age = age;
set-di.xml配置
①注入空字符串使用:<value/> 或者 value=""。
②注入null使用:<null/> 或者 不为该属性赋值。
<?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="carBean" class="com.bjpowernode.spring6.bean.Cat">
<!--注入null-->
<!--第一种方法:不为该属性赋值-->
<property name="name" value="张三"/>
<!--第二种方法:使用null标签,手动注入null-->
<property name="name">
<null/>
</property>
<property name="age" value="18"/>
<!-- 注入空字符串-->
<!--第一种方法-->
<property name="name" value=""/>
<!--第二种方法-->
<property name="name">
<value/>
</property>
<property name="age" value="20"/>
</bean>
</beans>
3.9 注入的值中含有特殊符号
(1)XML中有5个特殊字符,分别是:<、>、'、"、&
(2)以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。
Math类
package com.bjpowernode.spring6.bean;
public class Math
private String result;
@Override
public String toString()
return "Math" +
"result='" + result + '\\'' +
'';
public void setResult(String result)
this.result = result;
math.xml配置
解决方案包括两种:
第一种:特殊符号使用转义字符代替。
第二种:将含有特殊符号的字符串放到:<![CDATA[]]> 当中。因为放在CDATA区中的数据不会被XML文件解析器解析。
注:使用<![CDATA[]]>的方式只能使用value标签的形式,不能使用value属性!
注:<![CDATA[]]>是XML的语法,放在这里面的东西不会被XML解析器解析!
5个特殊字符对应的转义字符分别是:
特殊字符 | 转义字符 |
> | > |
< | < |
' | ' |
" | " |
& | & |
<?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="mathBean" class="com.bjpowernode.spring6.bean.Math">
<!--直接写2<3会报错-->
<!-- <property name="result" value="2<3"/>-->
<!--第一种解决方案:使用实体符号代替特殊符号-->
<property name="result" value="2 < 3"/>
<!--第二种解决方案:<![CDATA[]]>-->
<property name="result">
<!--只能使用value标签-->
<value><![CDATA[2<3]]></value>
</property>
</bean>
</beans>
4. p命名空间注入
(1)p命名空间是简化set方法注入的。
(2)使用p命名空间注入的前提条件包括两个:
第一:在XML头部信息中添加p命名空间的配置信息:xmlns:p="http://www.springframework.org/schema/p"
第二:p命名空间注入还是基于set注入的,只不过p命名空间注入可以让spring配置变的更加简单;所以需要对应的属性提供setter方法。
Dog类:提供了setter方法
package com.bjpowernode.spring6.bean;
import java.util.Date;
public class Dog
private String name;
private int age;
// 虽然简单类型,但是一般都是当做非简单类型对待
private Date date;
@Override
public String toString()
return "Dog" +
"name='" + name + '\\'' +
", age=" + age +
", date=" + date +
'';
public void setName(String name)
this.name = name;
public void setAge(int age)
this.age = age;
public void setDate(Date date)
this.date = date;
spring-p.xml配置
①在spring的配置文件头部添加p命名空间。
②使用:在<bean>标签中的class属性后面直接使用,对于简单类型属性赋值 p:属性名 = "属性值";对于非简单类型属性赋值p:属性名-ref = "属性值"。
<?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">
<!--原来注入的方式-->
<bean id="dogBean" class="com.bjpowernode.spring6.bean.Dog">
<property name="name" value="大黄"/>
<property name="age" value="3"/>
<property name="date" ref="nowDate"/>
</bean>
<!--p命名注入方式-->
<bean id="dogBean" class="com.bjpowernode.spring6.bean.Dog" p:name="大黄" p:age="3" p:date-ref="nowDate"/>
<bean id="nowDate" class="java.util.Date"/>
</beans>
测试程序
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.bean.Dog;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class PTest
@Test
public void testPTest()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-p.xml");
Object dogBean = applicationContext.getBean("dogBean", Dog.class);
System.out.println(dogBean);
执行结果:
如果把setter方法注释掉,会报错
5. c命名空间注入
(1)c命名空间是简化构造方法注入的。
(2)使用c命名空间的两个前提条件:
①第一:需要在xml配置文件头部添加信息: xmlns:c="http://www.springframework.org/schema/c"
②第二:需要提供构造方法。
MyTime类:提供了构造方法
package com.bjpowernode.spring6.bean;
public class MyTime
private int year;
private int month;
private int day;
public MyTime(int year, int month, int day)
this.year = year;
this.month = month;
this.day = day;
@Override
public String toString()
return "MyTime" +
"year=" + year +
", month=" + month +
", day=" + day +
'';
spring-c.xml配置
①在spring的配置文件头部添加c命名空间。
②使用:c:_0 下标方式或者c:name 参数名方式。
<?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: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="myTimeBean" class="com.bjpowernode.spring6.bean.MyTime">
<constructor-arg index="0" value="2022"/>
<constructor-arg index="1" value="1"/>
<constructor-arg index="2" value="14"/>
</bean>
<!--c命名注入方式-->
<bean id="myTimeBean" class="com.bjpowernode.spring6.bean.MyTime" c:_0="2022" c:_1="1" c:_2="14" />
</beans>
测试程序
package com.bjpowernode.spring6.test;
import com.bjpowernode.spring6.bean.MyTime;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CTest
@Test
public void testCDI()
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-c.xml");
MyTime myTimeBean = applicationContext.getBean("myTimeBean", MyTime.class);
System.out.println(myTimeBean);
执行结果:
如果把构造方法注释掉
注意:不管是p命名空间还 以上是关于Spring6| Spring对IoC的实现(核心重点)的主要内容,如果未能解决你的问题,请参考以下文章