前言:
学习内容来自于黑马的SSM学习。从零学习SSM,目前是spring内容。这内容主要是 IOC/DI配置管理第三方bean。
黑马程序员SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术_哔哩哔哩_bilibili
通过第一篇我们已经学习完了IOC的相关内容,这篇主要是学习Bean 的基础配置。
3 Bean的学习
3.1 Bean的基础配置
3.1.1Bean的基础配置
id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一
class:bean的类型,配置bean的全类名
注意这的class属性不能写实例化对象的全类名,需要写接口的,因为接口是没办法创建对象,并且spring中的IOC是基于接口来实现依赖注入。
3.1.2Bean的作用域
上文介绍了bean默认创建的单例的,如果需要创建非单例需要加上一个属性scope
singleton:单例(默认)
prototype:非单例
Spring支持几种不同的作用域,以满足不同的应用场景需求。以下是一些主要的Bean作用域:
- SIngleton(单例):在bean中默认作用域,spring只会创建一个bean实例,并且在容器的生命周期共享该实例
- Prototype(非单例):每次请求时都会创建一个新的 Bean 实例。次从容器中获取该 Bean 时都 会创建一个新实例,适用于状态非常瞬时的 Bean。
- Request(请求):每个 HTTP 请求都会创建一个新的 Bean 实例。仅在 Spring Web 应用程序 中有效,每个 HTTP 请求都会创建一个新的 Bean 实例,适用于 Web 应用中需求局局部性 Bean。
- Session(会话):Session 范围内只会创建一个 Bean 实例。该 Bean 实例在用户会话范围内共享,仅在 Spring Web 应用程序中有效,适用于与用户会话相关的 Bean。
3.2 Bean的实例化
bean本质上就是对象,对象在new的时候会使用构造方法完成,那创建bean也是使用构造方法完成的。基于这个知识点出发,我们来验证spring中bean的三种创建方式。
3.2.1 Bean的构造方法实例化
- 准备一个BookDao和BookDaoImpl类
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
-
配置Ban到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="bookDao" class="com.example.dao.Impl.BookDaoImpl"/>
</beans>
- 运行
- 如果在BookDaoImpl加入无参构造。
- 无参改成有参构造,发现报错。
通过Spring的构造方法实例化每一个类默认都会提供一个无参构造函数。
3.2.2 静态工厂实例化
(1)工厂创建Bean
创建2个类分别是OrderDao和OrderDaoImpl类 ,创建工厂,主要是给工厂提供静态方法
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
return new OrderDaoImpl();
}
}
(2)静态工厂实例化
如何交给Spring来管理
-
applicationContext.xml 中添加以下内容
<bean id="orderDao" class="com.example.Factory.OrderDaoFactory" factory-method="getOrderDao"/>
- 运行
(3)实例工厂
- 静态方法改成普通方法
public class OrderDaoFactory {
public OrderDao getOrderDao(){
return new OrderDaoImpl();
}
}
- 运行
交给Spring容器管理
- applicationContext.xml 中添加以下内容
- 运行结果
得出结果还是很麻烦,使用 FactoryBean
- 创建OrderDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法
public class OrderDaoFactoryBean implements FactoryBean<OrderDao> {
//代替原始实例工厂中创建对象的方法
public OrderDao getObject() throws Exception {
return new OrderDaoImpl();
}
//返回所创建类的Class对象
public Class<?> getObjectType() {
return OrderDao.class;
}
}
- 配置applicationContext.xml文件
<bean id="orderDao" class="com.example.Bean.OrderDaoFactoryBean"/>
- 运行
发现都是单例
只需要把 isSingleton 方法重写
3.3bean的生命周期
- 添加初始化和销毁方法
- 配置applicationContext.xml
<bean id="bookDao" class="com.example.dao.Impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
- 运行
发现销毁方法没有执行,因为Spring的IOC容器是运行在JVM中,main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了,所以需要我们执行必须手动关闭
(1)close关闭容器
applicationContext 没有关闭方法,但是ClassPathXmlApplicationContext 有
(2) 注册钩子关闭容器
在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器,调用ctx的registerShutdownHook()方法。
ctx.registerShutdownHook();
结论:close和registerShutdownHook
相同点:这两种都能用来关闭容器
不同点:close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。