第7章 Spring中的Bean的管理
目录/Contents
- 第7章 Spring中的Bean的管理
- 学习目标
- 了解Spring IoC容器的原理
- 掌握Bean标签及其属性的使用
- 熟悉Bean的实例化
- 掌握Bean的作用域
- 掌握Bean的装配方式
- 熟悉Bean的生命周期
- 学习内容
- 1 Spring IoC容器
- 1.1 BeanFactory接口
- 1.1.1 BeanFactory接口的常用方法
- 1.1.2 BeanFactory接口实例的语法格式
- 1.2 ApplicationContext接口
- 1.2.1 ApplicationContext接口的特点
- 1.2.2 ApplicationContext接口的常用实现类
- 2 Bean的配置
- 2.1 Spring容器所支持的配置文件格式
- 2.2 \<bean>元素的常用属性
- 2.3 \<bean>元素的常用子元素
- 2.4 普通的Bean通常只需定义id(或者name)和class两个属性
- 3 Bean的实例化
- 3.1 构造方法实例化
- STEP 01
- STEP 02
- STEP 03
- STEP 04
- STEP 05
- 3.2 静态工厂实例化
- STEP 01
- STEP 02
- STEP 03
- STEP 04
- STEP 05
- 3.3 实例工厂实例化
- STEP 01
- STEP 02
- STEP 03
- STEP 04
- STEP 05
- 4 Bean的作用域
- 4.1 singleton作用域
- 4.2 通过案例的方式演示Spring容器中singleton作用域的使用。
- STEP 01
- STEP 02
- STEP 03
- 4.3 prototype作用域
- 5 Bean的装配方式
- 5.1 基于XML的装配
- 5.1.1 两种基于XML的装配方式
- 5.1.2 a.属性setter方法注入
- 5.1.3 b.构造方法注入
- 5.2 基于注解的装配
- 5.2.1 XML与注解装配的比较
- 5.2.2 Spring的常用注解
- 5.2.3 下面通过案例演示如何使用注解来装配Bean
- STEP 01
- STEP 02
- STEP 03
- STEP 04
- STEP 05
- STEP 06
- STEP 07
- STEP 08
- STEP 09
- STEP 10
- 5.3 自动装配
- 5.3.1 如何实现自动装配
- 5.3.2 autowire属性的值
- 6 Bean的生命周期
- 6.1 Bean在不同作用域内的生命周期
- 6.2 Bean生命周期的两个时间节点
- 6.3 监控时间节点的方式
- STEP 01
- STEP 02
- STEP 03
- STEP 04
第7章 Spring中的Bean的管理
学习目标
了解Spring IoC容器的原理
掌握Bean标签及其属性的使用
熟悉Bean的实例化
掌握Bean的作用域
掌握Bean的装配方式
熟悉Bean的生命周期
学习内容
1 Spring IoC容器
1.1 BeanFactory接口
1.1.1 BeanFactory接口的常用方法
1.1.2 BeanFactory接口实例的语法格式
Spring提供了几个BeanFactory接口的实现类,其中最常用的是XmlBeanFactory,它可以读取XML文件并根据XML文件中的配置信息生成BeanFactory接口的实例,BeanFactory接口的实例用于管理Bean。XmlBeanFactory类读取XML文件生成BeanFactory接口实例的具体语法格式如下。
BeanFactory beanFactory=new XmlBeanFactory
(new FileSystemResource(”D:/bean.xml”));
1.2 ApplicationContext接口
1.2.1 ApplicationContext接口的特点
ApplicationContext接口建立在BeanFactory接口的基础之上,它丰富了BeanFactory接口的特性,例如,添加了对国际化、资源访问、事件传播等方面的支持。
ApplicationContext接口可以为单例的Bean实行预初始化,并根据<property>元素执行setter方法,单例的Bean可以直接使用,提升了程序获取Bean实例的性能。
1.2.2 ApplicationContext接口的常用实现类
2 Bean的配置
2.1 Spring容器所支持的配置文件格式
Spring容器支持XML和Properties两种格式的配置文件,在实际开发中,最常用的是XML格式的配置文件。XML是标准的数据传输和存储格式,方便查看和操作数据。在Spring中,XML配置文件的根元素是<beans>,<beans>元素包含<bean>子元素,每个<bean>子元素可以定义一个Bean,通过<bean>元素将Bean注册到Spring容器中。
2.2 <bean>元素的常用属性
2.3 <bean>元素的常用子元素
2.4 普通的Bean通常只需定义id(或者name)和class两个属性
<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">
<!--使用id属性定义bean1,对应的实现类为com.itheima.Bean1-->
<bean id="bean1" class="com.itheima.Bean1">
</bean>
<!--使用name属性定义bean2,对应的实现类为com.itheima.Bean2-->
<bean name="bean2" class="com.itheima.Bean2"/>
</beans>
3 Bean的实例化
3.1 构造方法实例化
下面通过一个案例演示Spring容器如何通过构造方法实例化Bean。
STEP 01
在IDEA中创建一个名为chapter07的Maven项目,然后在项目的pom.xml文件中配置需使用到的Spring四个基础包和Spring的依赖包。
<!– 这里只展示了一个依赖包-->
<!-- spring-expression的依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
STEP 02
创建一个名称为com.itheima的包,在该包中创建Bean1类。
package com.itheima;
public class Bean1 {
public Bean1(){
System.out.println("这是Bean1");
}
}
STEP 03
新建applicationBean1.xml作为Bean1类的配置文件,在该配置文件中定义一个id为bean1的Bean,并通过class属性指定其对应的实现类为Bean1。
<?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="bean1" class="com.itheima.Bean1"></bean>
</beans>
STEP 04
创建测试类Bean1Test,在main()方法中通过加载applicationBean1.xml配置文件初始化Spring容器,再通过Spring容器生成Bean1类的实例bean1,用来测试构造方法是否能实例化Bean1。
public class Bean1Test {
public static void main(String[] args){
// 加载applicationBean1.xml配置
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("applicationBean1.xml");
// 通过容器获取配置中bean1的实例
Bean1 bean=(Bean1) applicationContext.getBean("bean1");
System.out.print(bean); }
}
STEP 05
在IDEA中启动Bean1Test类,控制台会输出结果。
3.2 静态工厂实例化
下面通过一个案例演示如何使用静态工厂方式实例化Bean。
STEP 01
创建Bean2类,该类与Bean1类一样,只定义一个构造方法,不需额外添加任何方法。
package com.itheima;
public class Bean2 {
public Bean2(){
System.out.println("这是Bean2");
}
}
STEP 02
创建一个MyBean2Factory类,在该类中定义一个静态方法createBean(),用于创建Bean的实例。createBean()方法返回Bean2实例。
package com.itheima;
public class MyBean2Factory {
//使用MyBean2Factory类的工厂创建Bean2实例
public static Bean2 createBean(){
return new Bean2();
}
}
STEP 03
新建applicationBean2.xml文件,作为MyBean2Factory类的配置文件。
<?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-4.3.xsd">
<bean id="bean2"
class="com.itheima.MyBean2Factory"
factory-method="createBean"/>
</beans>
STEP 04
创建一个测试类Bean2Test,用于测试使用静态工厂方式是否能实例化Bean。
public class Bean2Test {
public static void main(String[] args) {
// ApplicationContext在加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationBean2.xml");
System.out.println(applicationContext.getBean("bean2"));
}
}
STEP 05
在IDEA中启动Bean2Test类,控制台会输出结果。
3.3 实例工厂实例化
下面通过一个案例演示如何使用实例工厂方式实例化Bean。
STEP 01
创建Bean3类,该类与Bean1一样,只需编写一个构造方法。
package com.itheima;
public class Bean3 {
public Bean3(){
System.out.println("这是Bean3");
}
}
STEP 02
创建一个MyBean3Factory类,在该类中定义无参构造方法,并定义createBean()方法用于创建Bean3对象。
package com.itheima;
public class MyBean3Factory {
public MyBean3Factory() {
System.out.println("bean3工厂实例化中");
}
public Bean3 createBean() { //创建Bean3实例的方法
return new Bean3();
}
}
STEP 03
新建applicationBean3.xml文件,作为MyBean3Factory类的配置文件。
<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-4.3.xsd">
<!-- 配置工厂 -->
<bean id="myBean3Factory” class="com.itheima.MyBean3Factory" />
<!-- 使用factory-bean属性指向配置的实例工厂-->
<bean id="bean3" factory-bean="myBean3Factory"
factory-method="createBean" />
</beans>
STEP 04
创建一个测试类BeanTest3,用于测试使用实例化工厂方式是否能实例化Bean。
public class Bean3Test {
public static void main(String[] args) {
// ApplicationContext在加载配置文件时,对Bean进行实例化
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationBean3.xml");
System.out.println(applicationContext.getBean("bean3"));
}
}
STEP 05
在IDEA中启动Bean3Test类,控制台会输出结果。
4 Bean的作用域
4.1 singleton作用域
Spring支持的5种作用域
4.2 通过案例的方式演示Spring容器中singleton作用域的使用。
STEP 01
将id为bean1的作用域设置为singleton。
<?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="bean1" class="com.itheima.Bean1" scope="singleton"></bean>
</beans>
STEP 02
创建测试类scopeTest,在main()方法中通过加载applicationBean1.xml配置文件初始化Spring容器,通过Spring容器获取Bean1类的两个实例,判断两个实例是否为同一个。
public class scopeTest{
public static void main(String[] args){
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("applicationBean1.xml");
Bean1 bean1_1=(Bean1) applicationContext.getBean("bean1");
Bean1 bean1_2=(Bean1) applicationContext.getBean("bean1");
System.out.print(bean1_1==bean1_2); }
}
STEP 03
在IDEA中启动scopeTest类,控制台会输出运行结果。
4.3 prototype作用域
prototype作用域的使用
<?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="bean1" class="com.itheima.Bean1" scope="prototype"></bean>
</beans>
5 Bean的装配方式
5.1 基于XML的装配
5.1.1 两种基于XML的装配方式
在基于XML的装配就是读取XML配置文件中的信息完成依赖注入,Spring容器提供了两种基于XML的装配方式,属性setter方法注入和构造方法注入。下面分别对这两种装配方式进行介绍。
5.1.2 a.属性setter方法注入
属性setter方法注入要求一个Bean必须满足以下两点要求。
(1)Bean类必须提供一个默认的无参构造方法。
(2)Bean类必须为需要注入的属性提供对应的setter方法。
5.1.3 b.构造方法注入
使用构造方法注入时,在配置文件里,需要使用元素的子元素来定义构造方法的参数,例如,可以使用其value属性(或子元素)来设置该参数的值。
5.2 基于注解的装配
5.2.1 XML与注解装配的比较
在Spring中,使用XML配置文件可以实现Bean的装配工作,但在实际开发中如果Bean的数量较多,会导致XML配置文件过于臃肿,给后期维护和升级带来一定的困难。为解决此问题,Spring提供了注解,通过注解也可以实现Bean的装配。
5.2.2 Spring的常用注解
5.2.3 下面通过案例演示如何使用注解来装配Bean
STEP 01
导入依赖:在项目chapter07的pom.xml文件中导入spring-aop-5.2.8.RELEASE.jar依赖包,导入代码如下所示。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
STEP 02
XML配置文件:创建applicationContext.xml,在该文件中引入Context约束并启动Bean的自动扫描功能。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.itheima" />
</beans>
STEP 03
定义实体类:新建entity包,在entity包下创建User实体类。
@Component("user")
@Scope("singleton")
public class User {
@Value("1")
private int id;
@Value("张三")
private String name;
@Value("123")
private String password;
// 省略getter/setter方法和toString()方法
}
STEP 04
定义dao层:创建UserDao接口作为数据访问层接口,并在UserDao接口中声明save()方法,用于查询User实体的对象信息。
package com.itheima.dao;
public interface UserDao {
public void save();
}
STEP 05
实现dao层:
创建UserDaoImpl作为UserDao的实现类,并在UserDaoImpl类中实现UserDao接口中的save()方法。
@Repository("userDao")
public class UserDaoImpl implements UserDao {
public void save(){
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("applicationContext.xml");
User user=(User) applicationContext.getBean("user");
System.out.println(user);
System.out.println("执行UserDaoImpl.save()");
}
}
STEP 06
定义service层:创建UserService接口作为业务逻辑层接口,并在UserService接口中定义save()方法。
package com.itheima.service;
public interface UserService {
public void save();
}
STEP 07
实现service层:创建UserServiceImpl作为UserService的实现类,并在UserServiceImpl类中实现UserService接口中的save()方法。
@Service("userService")
public class UserServiceImpl implements UserService {
//使用@Resource注解注入UserDao
@Resource(name="userDao")
private UserDao userDao;
public void save(){
this.userDao.save();
System.out.println("执行UserServiceImpl.save()");
}
}
STEP 08
定义controller层: 创建UserController类作为控制层。
@Controller
public class UserController {
//使用@Resource注解注入UserService
@Resource(name="userService")
private UserService userService;
public void save(){
this.userService.save();
System.out.println("执行UserController.save()");
}
}
STEP 09
定义测试类:创建测试类AnnotationTest,在该类中编写测试代码,通过Spring容器加载配置文件并获取UserController实例,然后调用实例中的save()方法。
public class AnnotationTest {
public static void main(String[] args){
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("applicationContext.xml");
UserController usercontroller=(UserController)
applicationContext.getBean("userController");
usercontroller.save();
}
}
STEP 10
查看运行结果:在IDEA中启动AnnotationTest类,控制台会输出结果。
5.3 自动装配
5.3.1 如何实现自动装配
Spring的元素中包含一个autowire属性,可以通过设置autowire属性的值实现Bean的自动装配。
5.3.2 autowire属性的值
6 Bean的生命周期
6.1 Bean在不同作用域内的生命周期
Bean的生命周期是指Bean实例被创建、初始化和销毁的过程。在Bean的两种作用域singleton和prototype中,Spring容器对Bean的生命周期的管理是不同的。在singleton作用域中,Spring容器可以管理Bean的生命周期,控制着Bean的创建、初始化和销毁。在prototype作用域中,
Spring容器只负责创建Bean实例,不会管理其生命周期。
6.2 Bean生命周期的两个时间节点
在Bean的生命周期中,有两个时间节点尤为重要,这两个时间节点分别是Bean实例初始化后和Bean实例销毁前,在这两个时间节点通常需要完成一些指定操作。因此,常常需要对这两个节点进行监控。
6.3 监控时间节点的方式
监控两个节点的方式有两种,一种是使用XML配置文件,一种是使用注解。
Spring容器提供了@PostConstruct用于监控Bean对象初始化节点, 提供了@PreDestroy用于监控Bean对象销毁节点。
下面通过案例演示这两个注解的使用。
STEP 01
创建Student类,在类中定义id和name字段,并使用@PostConstruct指定初始化方法,使用@PreDestroy指定Bean销毁前的方法。
@Component("student")
public class Student {
@Value("1")
private String id;
@Value("张三")
private String name; // 省略getter/setter方法,以及toString()方法
@PostConstruct
public void init(){System.out.println("Bean的初始化完成,调用init()方法"); }
@PreDestroy
public void destroy(){System.out.println("Bean销毁前调用destroy()方法"); }}
STEP 02
创建applicationStudent.xml,在该文件中引入Context约束并启动Bean的自动扫描功能。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 使用context命名空间,在配置文件中开启相应的注解处理器 -->
<context:component-scan base-package="com.itheima" />
</beans>
STEP 03
创建测试类StudentTest,在该类中编写测试代码,通过Spring容器加载配置文件并获取Student实例。
public class StudentTest {
public static void main(String[] args){
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("applicationStudent.xml");
Student student=(Student)applicationContext.getBean("student");
System.out.println(student);
//销毁Spring容器中的所有Bean
AbstractApplicationContext ac=(AbstractApplicationContext)
applicationContext;
ac.registerShutdownHook();
}}
STEP 04
在IDEA中启动StudentTest类,控制台会输出结果。