0


Spring《二》bean的实例化与生命周期

🍎道阻且长,行则将至。🍓

上一篇:Spring《一》快速入门
下一篇:Spring《三》DI依赖注入


目录


一、bean实例化🍍

在上一篇Spring快速入门👉🏻中,我们使用IOC容器进行对象的创建,在IOC中的对象也称为bean,那么IOC容器是怎么创建bean的呢。

下面介绍bean的实例化方法:

构造方法

静态工厂

实例工厂

1.构造方法 ***

  1. 我们先创建好一个maven项目,在maven配置文件pom中添加spring的依赖,再继续在resources文件夹下new个Spring的配置文件,applicationContext.xml。
  2. 准备好我们的接口和类:BookDaoBookDaoImpl:在接口添加一个save方法,到类中实现,输出一个语句示例。因为要使用构造方法,那我们就写一个无参构造器,并且在里面随便输出一个提示语句。
  3. 写好类之后,我们继续到Spring配置文件中将类配置到容器:<bean id="bookDao" name="book1" class="Demo1.dao.impl.BookDaoImpl"/>,我们可以发现在左侧出现spring的小标志了,表示配置正常;在这里插入图片描述
  4. 完成一个运行的程序,若最后可以打印构造器中的内容表示就是创建对象使用了构造函数。
publicclassAppForInstanceBook{publicstaticvoidmain(String[] args){ApplicationContext ctx=newClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao =(BookDao) ctx.getBean("bookDao");
        bookDao.save();}}

输出:
在这里插入图片描述
并且当构造器为私有的时候,仍然可以访问,说明了Spring的底层使用了反射。回顾参考👉🏻java反射机制
但是Spring只是使用无参构造器。

2.静态工厂 *

使用工厂创建对象

我们可以继续在前面的maven中类似地添加接口和类:

OrderDao

OrderDaoImpl

,然后在创建一个工厂类:

publicclassOrderDaoFactory{publicstaticOrderDaogetOrderDao(){returnnewOrderDaoImpl();}}

完成一个运行的程序,使用工厂获取对象:

publicclassAppForInstanceOrder{publicstaticvoidmain(String[] args){//通过静态工厂创建对象OrderDao orderDao =OrderDaoFactory.getOrderDao();
        orderDao.save();}}

在这里插入图片描述

实例化bean

要使用静态工厂实例化bean只需要在Spring配置文件中添加

<bean id="orderDao" name="Order1" class="Demo1.factory.OrderDaoFactory" factory-method="getOrderDao"/>

,注意class是指向工厂类,添加的工厂方法属性指向工厂中创建对象的方法;静态工厂实例化配置成功之后再工厂类中也会有提示:
在这里插入图片描述 👉 在这里插入图片描述
然后在运行方法中从容器获取bean:

ApplicationContext ctx=newClassPathXmlApplicationContext("applicationContext.xml");OrderDao orderDao =(OrderDao) ctx.getBean("orderDao");
orderDao.save();

3.实例工厂 ***

使用示例工厂创建对象

我们还是可以继续在前面的maven中类似地添加接口和类:

UserDao

UserDaoImpl

,再同样的创建一个工厂类:

OrderDaoFactory

,注意和静态工厂的不一样:

//UserDaopackageDemo1.dao;publicinterfaceUserDao{publicvoidsave();}//UserDaoImplpackageDemo1.dao.impl;importDemo1.dao.UserDao;publicclassUserDaoImplimplementsUserDao{@Overridepublicvoidsave(){System.out.println("userDao save...");}}//OrderDaoFactorypackageDemo1.factory;importDemo1.dao.UserDao;importDemo1.dao.impl.UserDaoImpl;publicclassUserDaoFactory{publicUserDaogetUserDao(){returnnewUserDaoImpl();}}

我们可以在运行程序中使用实例工厂获取对象:

publicclassAppForInstanceUser{publicstaticvoidmain(String[] args){//创建实例工厂对象UserDaoFactory userDaoFactory =newUserDaoFactory();//通过实例工厂对象创建对象UserDao userDao = userDaoFactory.getUserDao();
        userDao.save();}

我们想把这种实例工厂也交给Spring:

实例工厂实例化bean

在配置文件中添加:

<beanid="userFactory"class="Demo1.factory.UserDaoFactory"/><beanid="userDao"factory-method="getUserDao"factory-bean="userFactory"/>

在前面的静态工厂中我们只需要配置工厂类进来,使用静态方法就可以获得对象。而这需要先添加工厂,再添加Dao。
我们也可以修改验证一下为什么要这样,当你试图在工厂bean中加实例方法,直接给你报错:
在这里插入图片描述
其实想一想就知道了,这个不是静态方法啊,对象都没有你怎么使用这个方法。
然后在运行程序中添加:

ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao =(UserDao) ctx.getBean("userDao");
userDao.save();

在这里插入图片描述

上面的Spring配置还是太麻烦,改!

FactoryBean

Spring为了简化这种配置方式就提供了

FactoryBean

来简化开发。

创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法:

publicclassUserDaoFactoryBeanimplementsFactoryBean<UserDao>{@OverridepublicUserDaogetObject()throwsException{returnnewUserDaoImpl();}@OverridepublicClass<?>getObjectType(){returnUserDao.class;}}

就只需要一个

FactoryBean

的配置:

<bean id="userDao" class="Demo1.factory.UserDaoFactoryBean"/>

FactoryBean

的源代码也不长,我们可以打开看看:

publicinterfaceFactoryBean<T>{String OBJECT_TYPE_ATTRIBUTE ="factoryBeanObjectType";@NullableTgetObject()throwsException;@NullableClass<?>getObjectType();defaultbooleanisSingleton(){returntrue;}}

他提供了3个方法,我们在创建UserDaoFactoryBean的类的时候重写了两个接口的方法:

getObject()

,在方法中进行对象的创建并返回;

getObjectType()

,返回的是被创建类的Class对象;

isSingleton()

就是设置对象是否为单例,默认true。


二、生命周期🍑

生命周期就是从创建到消亡的完整过程。bean的生命周期自然是指bean对象从创建到销毁的过程。

1.生命周期设置

我们想设置:

  • bean创建之后,想要添加内容,比如用来初始化需要用到资源
  • bean销毁之前,想要添加内容,比如用来释放用到的资源 继续在前面的案例中,我们在实例工厂类添加:
publicvoidinit(){System.out.println("init userDaofac...");}publicvoiddestory(){System.out.println("destory userDaofac...");}

在bean中追加:

init-method="init" destroy-method="destory"


在这里插入图片描述
只有初始化被执行了。问:为什么?
Spring的IOC容器是运行在JVM中,运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行。然而main方法执行完后,JVM就退出了,这个时候IOC容器中的bean也就结束了,根本没有调用destroy方法。
所以这个时候我们可以

在main方法使用close

使用钩子关闭容器

2.在main方法使用close

ApplicationContext 

中没有提供close方法,我们需要使用

ClassPathXmlApplicationContext 


修改

ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");
⇨ 
ClassPathXmlApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");

就可以使用:

ctx.close();

了。
在这里插入图片描述

3.使用钩子关闭容器

就是在容器未关闭之前,提前设置好回调函数,让JVM可以在退出之前回调此函数来关闭容器。
就是把前面的

ctx.close();

换为

ctx.registerShutdownHook();

需要修改配置文件还是太麻烦,再改!

前面的方法还是需要在Spring配置文件中添加bean的

init-method

destroy-method

,Spring对此进行简化,提供了两个接口来完成生命周期的控制,而不用再进行配置

InitializingBean

DisposableBean


在类里面继承接口并重写:

publicclassUserDaoFactoryBeanimplementsFactoryBean<UserDao>,InitializingBean,DisposableBean{@OverridepublicUserDaogetObject()throwsException{returnnewUserDaoImpl();}@OverridepublicClass<?>getObjectType(){returnUserDao.class;}//************************@Overridepublicvoiddestroy()throwsException{System.out.println("destory...");}@OverridepublicvoidafterPropertiesSet()throwsException{System.out.println("ini...");}}

在运行程序仍然使用

ctx.registerShutdownHook();


在这里插入图片描述


☕物有本末,事有终始,知所先后。🍭

🍎☝☝☝☝☝我的CSDN☝☝☝☝☝☝🍓

标签: spring java 后端

本文转载自: https://blog.csdn.net/weixin_42204569/article/details/129770327
版权归原作者 Super algorithm 所有, 如有侵权,请联系我们删除。

“Spring《二》bean的实例化与生命周期”的评论:

还没有评论