二、Bean的实例化
问题导入
Bean的实例化方式有几种?
1. Bean是如何创建的
bean本质上就是对象,创建bean使用构造方法完成
2. 实例化Bean的三种方式
2.1 构造方法方式【重点】
BookDaoImpl实现类 public class BookDaoImpl implements BookDao { public BookDaoImpl() { System.out.println("book dao constructor is running ...."); } public void save() { System.out.println("book dao save ..."); } }
applicationContext.xml配置、
<!--方式一:构造方法实例化bean--> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
AppForInstanceBook测试类
public class AppForInstanceBook { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); bookDao.save(); } }
运行结果
注意:无参构造方法如果不存在,将抛出异常BeanCreationException
2.2 静态工厂方式
OrderDao接口和OrderDaoImpl实现类 public interface OrderDao { public void save(); } public class OrderDaoImpl implements OrderDao { public void save() { System.out.println("order dao save ..."); } }
OrderDaoFatory工厂类
//静态工厂创建对象 public class OrderDaoFactory { public static OrderDao getOrderDao(){ System.out.println("factory setup...."); return new OrderDaoImpl(); } }
applicationContext.xml配置
<!--方式二:使用静态工厂实例化bean--> <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
AppForInstanceOrder测试类
public class AppForInstanceOrder { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); OrderDao orderDao = (OrderDao) ctx.getBean("orderDao"); orderDao.save(); } }
运行结果
2.3 实例工厂方式
UserDao接口和UserDaoImpl实现类
public interface UserDao { public void save(); } public class UserDaoImpl implements UserDao { public void save() { System.out.println("user dao save ..."); } }
UserDaoFactory工厂类
//实例工厂创建对象 public class UserDaoFactory { public UserDao getUserDao(){ return new UserDaoImpl(); } }
applicationContext.xml配置
<!--方式三:使用实例工厂实例化bean--> <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/> <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
AppForInstanceUser测试类
public class AppForInstanceUser { public static void main(String[] args) { // //创建实例工厂对象 // UserDaoFactory userDaoFactory = new UserDaoFactory(); // //通过实例工厂对象创建对象 // UserDao userDao = userDaoFactory.getUserDao(); // userDao.save(); ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) ctx.getBean("userDao"); userDao.save(); } }
运行结果
2.4 实现FactoryBean<T>方式
定义UserDaoFactoryBean实现FactoryBean<UserDao>
UserDaoFactoryBean中实例化什么类型的对象泛型就是该类型。
//FactoryBean创建对象 public class UserDaoFactoryBean implements FactoryBean<UserDao> { //代替原始实例工厂中创建对象的方法 public UserDao getObject() throws Exception { return new UserDaoImpl(); } public Class<?> getObjectType() { return UserDao.class; } }
applicationContext.xml配置
<!--方式四:使用FactoryBean实例化bean--> <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
使用之前的AppForInstanceUser测试类去运行看结果就行了。注意配置文件中id="userDao"是否重复。
三、Bean的生命周期
问题导入
问题1:多例的Bean能够配置并执行销毁的方法?
问题2:如何做才执行Bean销毁的方法?
1. 生命周期相关概念介绍
生命周期:从创建到消亡的完整过程
bean生命周期:bean从创建到销毁的整体过程
bean生命周期控制:在bean创建后到销毁前做一些事情
2. 代码演示
2.1 Bean生命周期控制
提供生命周期控制方法
public class BookDaoImpl implements BookDao { 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..."); } }
applicationContext.xml配置
<!--init-method:设置bean初始化生命周期回调函数,此处填写init方法名--> <!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象,此处填写destory方法名--> <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
测试类
public class AppForLifeCycle { public static void main( String[] args ) { //此处需要使用实现类类型,接口类型没有close方法 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); bookDao.save(); //关闭容器,执行销毁的方法 ctx.close(); } }
2.2 Bean生命周期控制
实现InitializingBean, DisposableBean接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean { private BookDao bookDao; public void setBookDao(BookDao bookDao) { System.out.println("set ....."); this.bookDao = bookDao; } public void save() { System.out.println("book service save ..."); bookDao.save(); } public void destroy() throws Exception { System.out.println("service destroy"); } public void afterPropertiesSet() throws Exception { System.out.println("service init"); } }
测试类代码同《3.2.1 Bean生命周期控制》中的测试代码
3. Bean销毁时机
容器关闭前触发bean的销毁
关闭容器方式:
手工关闭容器
ConfigurableApplicationContext接口close()操作
注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
ConfigurableApplicationContext接口registerShutdownHook()操作 public class AppForLifeCycle { public static void main( String[] args ) { //此处需要使用实现类类型,接口类型没有close方法 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); bookDao.save(); //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器 ctx.registerShutdownHook(); //关闭容器 //ctx.close(); } }