【Spring】实例化bean的三种方式、bean的生命周期控制操作(代码解释)

bean是如何创建出来的?

bean实例化——1.构造方法

  • 本质上是对象,创建bean使用构造方法完成的。
//dao层接口:
public interface UserDao {
	public void save(User user);
}
配置 
<bean id="userDao" class="com.jules.dao.impl.UserDaoImpl"/>
//dao层实现类
public class UserDaoImpl implements UserDao {
	//提供可访问的构造方法
	//private UserDaoImpl(){}私有的也可以使用(反射)
	public UserDaoImpl() {
		System.out.println("执行UserDaoImpl的构造方法……");
	}
	public void save(User user) {		
		System.out.println("保存用户信息到数据库~");
	}
}
//测试类:
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao = (userDao) context.getBean("userDao");
    userDao.save();

打印结果:-------------------------------------------------
执行UserDaoImpl的构造方法……
保存用户信息到数据库~

  • 【Spring创建bean调的是无参的构造方法,并且私有的方法也可以使用】
  • 【无参的构造方法如果不存在(有参),将会抛出异常BeanCreationException】

bean实例化——2.静态工厂

//dao层接口:
public interface UserVODao {
	public void save();
}
//dao层实现类
public class UserVODaoImpl implements UserVODao {
	public void save() {		
		System.out.println("UserVODao 保存~");
	}
}
public class UserVODaoFactory{
	//静态工厂----
	public static UserVODao getUserVODao(){
		//System.out.println("factory 创建~");
		return new  UserVODaoImpl();
	}
}
//以前的测试类:
	//通过静态工厂创建对象
	UserVODao userVODao = new userVODaoFactory.getUserVODao();
	userVODao.save();
	
//控制台输出-------------:UserVODao 保存~

=换模式:

<!--配置:使用静态工厂示例bean。-->
<!--注意:不仅要完全限定名到工厂类,还要factory-method指定工厂-->
<bean id="userVODao" class="com.jules.factory.UserVODaoFactory" factory-method="getUserVODao"/>
//测试类:
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserVODao userVODao = (userVODao) context.getBean("userVODao");
    userVODao.save();

bean实例化——3.实例工厂

//dao层接口:
public interface UserVODao {
	public void save();
}
//dao层实现类
public class UserVODaoImpl implements UserVODao {
	public void save() {		
		System.out.println("UserVODao 保存~");
	}
}
public class UserVODaoFactory{
	//工厂----
	public UserVODao getUserVODao(){
		return new  UserVODaoImpl();
	}
}
//以前的测试类:
	//创建实例工厂对象
	UserVODaoFactory userVODaoFactory = new UserVODaoFactory();
	//通过实例工厂对象创建对象
	UserVODao userVODao = new userVODaoFactory.getUserVODao();
	userVODao.save();
	
//控制台输出:UserVODao 保存~

=换模式:

<!--配置:使用实例工厂示例bean-->
	<!--先创建工厂的实例对象-->
	<bean id="userFactory" class="com.jules.factory.UserVODaoFactory" />
	<!---->
	<bean id="userVODao" factory-method="getUserVODao" factory-bean="userFactory"/>
//测试类:
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserVODao userVODao = (userVODao) context.getBean("userVODao");
    userVODao.save();

bean实例化——4.FactoryBean(改良方法3)

【在spring中实例化bean的实例工厂方法的配置文件会有多余:接下来处理无用bean和方法的固定】

在这里插入图片描述

步骤:
  • 1.创建一个UserDaoFactoryBean的工厂实现接口FactoryBean,此处泛型,你用它造什么对象就写什么

    public class UserDaoFactoryBean implements FactoryBean<UserVODao> {
    	//代替原始实例工厂中创建对象的方法
    	public UserDaoVO getobject() throws Exception {
    		return new UserDaoVOImpl();
    	}
    	//设置类型:对象什么类型
    	public class<?> getobjectType() {
    		return UserDaoVO.class;
    	}
    }
    
  • 2.按照此种工厂配置bean

    <bean id="userVODao" class="com.jules.factory.UserDaoFactoryBean"/>
    

【此时继续测试,依旧可行,并且还是单例模式,如何非单例呢?】
在 UserDaoFactoryBean 类中写方法:

public boolean isSingleton() {
	//return true;  //单例
	return true;  //非单例
}

bean生命周期控制

  • bean生命周期:bean从创建到销毁的整体过程
  • bean生命周期控制:在bean创建后到销毁做的一些事情
  • 上代码解释bean生命周期控制的两种方法-----------------------------------------------:
方法一、用配置控制:init-method、destory-method
//dao层接口:
public interface UserDao {
	public void save(User user);
}

【在dao实现里面写两个方法--初始化和销毁方法,此时这两个方法是不能代表真正的初始化和销毁,需要在配置文件中配置:】

//提供生命周期控制方法
public class UserDaoImpl implements UserDao {
	public void save(User user) {		
		System.out.println("保存用户信息到数据库~");
	}
	public void init(){
		System.out.println("初始化init方法……");
	}
	public void destory(){
		System.out.println("销毁destory方法……");
	}
}

【配置bean生命周期的方法:init-method 和 destory-method】

<bean id="userDao" class="com.jules.dao.impl.UserDaoImpl" init-method="init" destory-method="destory"/>
//测试类:
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao = (userDao) context.getBean("userDao");
    userDao.save();

控制台打印结果:-------------------------------------
初始化init方法……
保存用户信息到数据库~

【看到输出结果你会发现,只执行了初始化方法,并没有销毁,why?如何让它销毁呢?】

我们现在的程序是写在java虚拟机中,虚拟机启动了,IoC容器加载了配置applicationContext.xml,把bean初始化了,从中拿到beangetBean()执行完程序,虚拟机退出了,但在退出过程中没有给bean一个销毁的状态。

如何销毁?就是让容器关闭了,关闭容器的两种方法:

  • ①在虚拟机退出之前手动把容器关闭了close()方法此种方法比较暴力,直接关闭容器

    ApplicationContext中并没有close()方法,子类ConfigurableApplicationContext接口中有close()方法,new对象ClassPathXmlApplicationContext类可以使用close()。

    简单说一下他们三个的关系:ApplicationContext父类接口—子类ConfigurableApplicationContext接口----ClassPathXmlApplicationContext实现类

    看图更清晰:close()根源是ConfigurableApplicationContext接口中的方法
    在这里插入图片描述

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //context.close();//不可以放这里,报错
    UserDao userDao = (userDao) context.getBean("userDao");
    userDao.save();
    context.close();
    

    控制台打印结果:此时可以看到销毁过程已执行----------------------
    初始化init方法……
    保存用户信息到数据库~
    销毁destory方法……

  • ②注册关闭钩子:容器启动以后,加一个标志ConfigurableApplicationContext接口registerShutdownHook()操作,让虚拟机退之前,先把容器关闭后再退。

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //注册关闭钩子,关虚拟机之前先把容器关了。
    context.registerShutdownHook();
    UserDao userDao = (userDao) context.getBean("userDao");
    //context.registerShutdownHook();  //在任何时间都可以,放这里执行也行
    userDao.save();
    

close()和registerShutdownHook()的区别:

  • close(); 暴力,说关就关,所以只能放在最后,如果放在getBean前面,会报错BeanFactory not initializes or already closed……
  • registerShutdownHook(); 就比较灵活,告知关闭虚拟机之前先把容器关闭,方法都可以执行。

【在实际开发中,此过程我们不需要写,我们最终做的是web应用,关闭容器这件事会伴随Tomcat】

方法二、使用接口,实现InitializingBean, DisposableBean接口:

上述范例中的初始化和销毁使我们随便写的,通过配置让它转为真正的初始化和销毁方法,这样不规范,spring就给我们提供了接口,就不用再配置在中init-method="init" destory-method="destory"

public class UserDaoImpl implements UserDao, InitializingBean, DisposableBean {
	public void save(User user) {		
		System.out.println("保存用户信息到数据库~");
	}
	public void destory() throws Exception {
		System.out.println("destory……");
	}
	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet……");
	}
}
public static void main(String[] args) {
	ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao = (userDao) context.getBean("userDao");
    userDao.save();
    context.close();
}

控制台打印结果:-------------------------------
afterPropertiesSet……
保存用户信息到数据库~
destory……

【解释一下afterPropertiesSet(),上述案例我是在dao层实现中测试的,若换到service层的实现,直接上个图,观察一下:】
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱尔斯Jules

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值