


思考:
(1)为什么bean默认为单例?
1️⃣bean为单例的意思是在Spring的IoC容器中只会有该类的一个对象
2️⃣bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
(2)bean在容器中是单例的,会不会产生线程安全问题?1️⃣如果对象是有状态对象,即该对象有成员变量可以用来存储数据的,因为所有请求线程共用一个bean对象,所以会存在线程安全问题
2️⃣如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的,因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题
(3)哪些bean对象适合交给容器进行管理?
表现层对象、业务层对象、数据层对象、工具对象
(4)哪些bean对象不适合交给容器进行管理?
封装实例的域对象,因为会引发线程安全问题,所以不适合。
bean 本质上就是对象,对象在 new 的时候会使用构造方法完成,那创建 bean 也是使用构造方法完成的。
实例化 bean 的三种方式: 构造方法(常用) 、 静态工厂(了解) 、 实例工厂、 实例工厂的FactoryBean(实用)
(1) 准备一个 OrderDao 和 OrderDaoImpl 类
public interface OrderDao { void save(); }
public class OrderDaoImpl implements OrderDao { @Override public void save() { System.out.println("order dao save..."); } }
(2) 创建一个工厂类 OrderDaoFactory 并提供一个 静态方法
public class OrderDaoFactory { public static OrderDao getOrderDao() { System.out.println("factory setup..."); return new OrderDaoImpl(); } }
(3) 在 spring 的配置文件 application.properties 中添加以下内容 :
"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="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/> beans>class: 工厂类的类全名factory-mehod: 具体工厂类中创建对象的方法名
(4) 在 AppForInstanceOrder 运行类,使用从 IOC 容器中获取 bean 的方法进行运行测试
/** * bean的实例化方式:静态工厂 */ public class AppForInstanceOrder { public static void main(String[] args) { //通过静态工厂创建对象 // OrderDao orderDao = OrderDaoFactory.getOrderDao(); // orderDao.save(); ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); OrderDao orderDao = (OrderDao) ctx.getBean("orderDao"); orderDao.save(); } }
(1)准备一个 UserDao 和 UserDaoImpl 类
public interface UserDao { void save(); }
public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("user dao save..."); } }
(2) 创建一个工厂类 OrderDaoFactory 并提供一个普通方法
public class UserDaoFactory { public UserDao getUserDao() { System.out.println("factory setup..."); return new UserDaoImpl(); } }
(3) 在 spring 的配置文件 application.properties 中添加以下内容 :
"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="userFactory" class="com.itheima.factory.UserDaoFactory"/> <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/> beans>![]()
(4) 在 AppForInstanceOrder 运行类,使用从 IOC 容器中获取 bean 的方法进行运行测试
/** * bean的实例化方式:实例工厂 */ public class AppForInstanceUser { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) ctx.getBean("userDao"); userDao.save(); } }
![]()
普通实例工厂实例化,配置复杂,可以优化
(1) 创建一个 UserDaoFactoryBean 的类,实现 FactoryBean 接口,重写接口的方法
public class UserDaoFactoryBean implements FactoryBean{ //代替原始实例工厂中创建对象的方法 @Override public UserDao getObject() throws Exception { return new UserDaoImpl(); } @Override public Class> getObjectType() { return UserDao.class; } @Override public boolean isSingleton() { //true:单例 //false:非单例 return false; } }方法一 :getObject() ,被重写后,在方法中进行对象的创建并返回方法二: getObjectType(), 被重写后,主要返回的是被创建类的 Class 对象方法三: 没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true ,
(2) 在 spring 的配置文件 application.properties 中添加以下内容 :
"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="userDao" class="com.itheima.factory.UserDaoFactoryBean"/> beans>
生命周期:从创建到消亡的完整过程
bean生命周期:bean从创建到销毁的整体过程
bean生命周期控制:在bean创建后到销毁前做一些事情
(1) 项目中添加 BookDao 、 BookDaoImpl 、 BookService 和 BookServiceImpl 类
public class BookDaoImpl implements BookDao { @Override public void save() { System.out.println("book dao save..."); } //表示bean初始化对应的操作 public void init() { System.out.println("init..."); } //表示bean销毁前对应的操作 public void destory() { System.out.println("destory..."); } }
(2)resources 下提供 spring 的配置文件
"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.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory" /> beans>
(4) 在 AppForLifeCycle 运行类, 进行运行测试
public class AppForLifeCycle { @Test public void test1() { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); bookDao.save(); //暴力关闭容器 ctx.close(); } @Test public void test2() { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); // 任意位置 ctx.registerShutdownHook(); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); bookDao.save(); } }
- public class BookServiceImpl implements BookService,
- InitializingBean, DisposableBean {
-
- private BookDao bookDao;
-
- @Override
- public void save() {
- System.out.println("book service save...");
- bookDao.save();
- }
-
- public void setBookDao(BookDao bookDao) {
- this.bookDao = bookDao;
- }
-
- @Override
- public void destroy() throws Exception {
- System.out.println("service destory");
- }
-
- //属性设置完成后触发
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("service init");
- }
- }