Bean的作用域和生命周期

开发者不仅可以控制注入不同的依赖到Bean之中,也可以配置Bean的作用域。这种方法是非常强大而且弹性也非常好的。开发者可以通过配置来指定对象的作用域,而不用在Java类层次上来配置。Bean可以配置多种作用域。 Spring框架支持5种作用域,有三种作用域是当开发者使用基于web的ApplicationContext的时候才生效的。

一、Bean的作用域

在这里插入图片描述

作用域描述
单例(singleton)(默认)每一个Spring IoC容器都拥有唯一的一个实例对象
原型(prototype)一个Bean定义可以创建任意多个实例对象
请求(request)一个HTTP请求会产生一个Bean对象,也就是说,每一个HTTP请求都有自己的Bean实例。只在基于web的Spring ApplicationContext中可用
会话(session)限定一个Bean的作用域为HTTPsession的生命周期。同样,只有基于web的Spring ApplicationContext才能使用
全局会话(global session)限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于web的Spring ApplicationContext可用
应用(application)限定一个Bean的作用域为ServletContext的生命周期。同样,只有基于web的Spring ApplicationContext可用

Spring的单例Bean和与设计模式之中的所定义的单例模式是有所区别的。设计模式中的单例模式是将一个对象的作用域硬编码的,一个ClassLoader只有唯一的一个实例。 而Spring的单例作用域,是基于每个容器,每个Bean只有一个实例。这意味着,如果开发者根据一个类定义了一个Bean在单个的Spring容器中,那么Spring容器会根据Bean定义创建一个唯一的Bean实例。 单例作用域是Spring的默认作用域,下面的例子是在基于XML的配置中配置单例模式的Bean。

新建beanScope-applicationContext.xml
    <bean id = "myCoach"
    	class = "springdemo.TrackCoach">
    	
    	    <!-- set up constructer injection -->
    	    <constructor-arg ref = "myFortune" />
    	</bean>
新建BeanScopeDemo .java
public class BeanScopeDemo {
	public static void main(String[] args) {
		// load the spring configuration file
		ClassPathXmlApplicationContext context = 
				new ClassPathXmlApplicationContext("beanScope-applicationContext.xml");
		//retrieve bean from spring container
		Coach theCoach = context.getBean("myCoach",Coach.class);
		
		Coach alphaCoach = context.getBean("myCoach",Coach.class);
		//check if they are the same
		boolean result = (theCoach == alphaCoach);
		//print out the results
		System.out.println("\nPointing to the same object:" + result);
		
		System.out.println("\nMemory location for theCoach"+theCoach);
		
		System.out.println("\nMemory location for alphaCoach"+alphaCoach + "\n");
		
		//close the context
		context.close();
	}
}
Pointing to the same object:true
Memory location for theCoachspringdemo.TrackCoach@10bbd20a
Memory location for alphaCoachspringdemo.TrackCoach@10bbd20a

2.prototype的bean scope就可以创建多个实例对象

修改xml文件

    <bean id = "myCoach"
    	class = "springdemo.TrackCoach"
    	scope = "prototype">

输出结果:

Pointing to the same object:false

Memory location for theCoachspringdemo.TrackCoach@10bbd20a

Memory location for alphaCoachspringdemo.TrackCoach@48503868

二、 Bean生命周期

Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean.。
在这里插入图片描述在spring的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等。

新建BeanLifeCycleDemo.java
public class BeanLifeCycleDemo {

	public static void main(String[] args) {
		// load the spring configuration file
		ClassPathXmlApplicationContext context = 
		new ClassPathXmlApplicationContext("beanLifeCycle-applicationContext.xml");	
		//retrieve bean from spring container
		Coach theCoach = context.getBean("myCoach",Coach.class);
	System.out.println(theCoach.getDailyWorkout());
		
		//close the context
		context.close();
	}
}


在TrackCoach.java中定义初始化TrackCoach

public class TrackCoach implements Coach {
	public void doMystartupStuff() {
		System.out.println("TrackCoach: inside method doMyStartupStuff");
	}
	
	//add a destroy method
	public void doMyCleanupStuffYoYo() {
		System.out.println("TrackCoach: inside method doMyCleanupStuffYoYo");
	}
	}
TrackCoach: inside method doMyStartupStuff
Run a hard 5k
TrackCoach: inside method doMyCleanupStuffYoYo
    <bean id = "myCoach"
    	class = "springdemo.TrackCoach"
    	init-method = "doMystartupStuff"
    	destroy-method = "doMyCleanupStuffYoYo">
使用annatotion(java注释)设置生命周期
	@PostConstruct
	public void doMyStartupStuff() {
		System.out.println(">> TennisCoach: doMyStartupStuff");
	}
	//define destory method
	@PreDestroy
	public void doMyCleanupStuff() {
		System.out.println(">> TennisCoach: doMyCleanupStuff");
	}

运行main函数输出结果:

>> TennisCoach: doMyStartupStuff
The journey is the reward
>> TennisCoach: doMyCleanupStuff
使用annatotion)设置bean scope

首先看他默认使用的是singleton作用域,在创建对象的时候link到同一个内存空间:

public class AnnotatioonBeanScopeDemoApp {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = 
				new ClassPathXmlApplicationContext("applicationContext.xml");
	
		Coach theCoach = context.getBean("tennisCoach",Coach.class);
		
		Coach alphaCoach  = context.getBean("tennisCoach",Coach.class);
	
		System.out.println(theCoach == alphaCoach);
		System.out.println("Memory location for theCoach:"+theCoach);
		System.out.println("Memory location for alphaCoach:"+alphaCoach);
	}

}
true
Memory location for theCoach:com.luv2code.springdemo.TennisCoach@36f0f1be
Memory location for alphaCoach:com.luv2code.springdemo.TennisCoach@36f0f1be

更改scope的方法:

@Component
@Scope("prototype")
public class TennisCoach implements Coach {

每次会创建不同的bean对象:

false
Memory location for theCoach:com.luv2code.springdemo.TennisCoach@ca263c2
Memory location for alphaCoach:com.luv2code.springdemo.TennisCoach@589b3632
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值