bean概念
§ bean配置
id
bean的id,使用容器可以通过id获取对应的bean,在一个容器中,id唯一
class
bean的类型,即配置的bean的全路径名称
name
bean的别名,多个别名可以用
,
、;
或空格分割在获取bean,或配置中的ref使用时可以使用别名
也必须唯一,否贼会报错
scope
Spring创建的bean默认为单例,使用该属性指定是否单例
- singleton(默认):单例
- prototype:非单例
<bean id="bookDao" name="b1" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype" />
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<!-- 配置serve与dao的关系
property表示配置当前bean的属性
name表示配置哪一个具体的属性(private Bookdao bookdao)
ref表示参照哪一个bean配置
-->
<property name="bookDao" ref="b1" />
</bean>
适合交给容器管理的bean
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
不适合
- 封装实体的对象
§ bean的实例化
调用无参构造方法
Spring通过反射默认调用无参构造方法构造
使用静态工厂
使用静态工厂实例化bean
目的:解决早期的一些使用工厂创建的遗留项目
数据层代码
public interface OrderDao {
void save();
}
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("Order save dao");
}
}
bean配置
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao" />
app代码
OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");
orderDao.save();
工厂代码
public class OrderDaoFactory {
public static OrderDao getOrderDao() {
System.out.println("factory");
return new OrderDaoImpl();
}
}
使用实例工厂
<bean id="orderDaoFactory" class="com.itheima.factory.OrderDaoFactory" />
<bean id="orderDao" factory-bean="orderDaoFactory" factory-method="getOrderDao" />
§ FactoryBean
上述使用实例工厂创建了一个工厂的bean,是一个多余的步骤
使用FactoryBean简化工厂创建的步骤
public class OrderDaoFactoryBean implements FactoryBean<OrderDao> {
// 代替原始实例工厂中创建对象的方法
@Override
public OrderDao getObject() throws Exception {
return new OrderDaoImpl();
}
@Override
public Class<?> getObjectType() {
return OrderDao.class;
}
// 是否是单例,不是直接返回false
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactoryBean" />
§ bean生命周期
- 生命周期:从创建到消亡的过程
- bean生命周期:bean从创建到销毁的整个过程
- bean生命周期控制:在bean创建后到销毁前做一些事情
配置方法
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book save dao");
}
// 表示bean初始化对应的操作
public void init() {
System.out.println("init dao");
}
// 表示bean销毁前对应的操作
public void destroy() {
System.out.println("destroy dao");
}
}
<bean id="bookDao" name="b1" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
打印结果
init
book dao save
可见没有执行destory
要销毁bean,方法如下
- 手动关闭容器:
ApplicationContext
换成具体实现类ClassPathXmlApplicationContext
后,调用ctx.close()
- 设置关闭钩子:
ApplicationContext
换成具体实现类ClassPathXmlApplicationContext
后,调用ctx.regusterShutdownHook()
区别:前者必须在不使用bean后调用,后者可以随时调用
这两个关闭操作都来自
ClassPathXmlApplicationContext
实现的接口ConfigurableApplicationContext
实现接口方法
使用工厂实例化bean无法触发一下的init和destroy
实现接口
InitializingBean
和DisposableBean
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
public void save() {
System.out.println("book service save");
bookDao.save();
}
// 提供对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void destroy() throws Exception {
System.out.println("destroy service");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("init service");
}
}
<bean id="bookDao" name="b1" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="b1" />
</bean>
生命周期
- 初始化容器
- 创建对象(分配内存)
- 执行构造方法
- 执行属性注入(set操作)
- 执行bean初始化方法
- 使用bean
- 执行业务操作
- 关闭bean
- 执行bean销毁方法
service和dao都实现InitializingBean
和DisposableBean
接口后执行service.save()
结果如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KflvUApY-1683549857607)(assets/image-20230216185227019.png)]