Spring学习手札(四)谈谈Spring Bean的生命周期及作用域
在Spring中,那些组成应用程序的主体以及由Spring IoC容器所管理的对象,被称之为Bean。Bean与应用程序中其他对象(比如自己创建类)的区别就是,Bean是由IoC容器创建于销毁的。在Spring中,每次从BeanFactory或ApplicationContext指定病获取Bean时都会产生一个新的实例,且默认都是单例。
Spring Bean生命周期比较复杂,可以分为创建和销毁创建
1.实例化Bean对象
2.设置Bean属性
Bean实例生命周期的知性过程如下:
* Spring实例化一个bean,就是new
* Spring会在配置说明,也就是IoC注入
* 如果这个Bean已经实现了Aware接口,会调用它实现setBeanName方法,次数传递的就是Spring配置中Bean的id值
* 如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
* 如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);
* 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
* 如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
* 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;
注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
* Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
* 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
Spring Bean的销毁过程调用了DisposableBean的destory方法和Bean自身定制的destory方法。
Spring Bean有5个作用域
Singleton,Spring的默认作用域,也就是为每个IoC容器创建唯一的一个Bean实例。适合无状态的Bean
Prototype,针对每个getBean请求,容器都会单独创建一个Bean实例。适合有状态的Bean,相当于new xxBean()
Request,为每个HTTP请求创建单独的Bean实例,适用于WebApplicationContext 环境
Session,同一个Http Session才能共享一个Bean,适用于WebApplicationContext 环境
GlobalSession,用于Portlet容器,因为每个Portlet有单独的Session,GlobalSession提供一个全局性的Http Session,适用于WebApplicationContext 环境
关于Spring Bean作用域再做补充
1.Spring中的bean默认都单例Singleton(bean的Id唯一),就是说容器在创建一个bean对象后,不管是使用与否,它都切实的存在,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中却省的作用域。
<bean name="userService" class="service.UserService" scope="singleton"></bean>
2.当一个bean的作用域为Prototype时,表示这个bean定义对应了多个对象实例,每次getBean()时,都会创建一个新的bean实例。Prototype,在我们创建容器的时候并没有实例化,而是我们获取bean的时候才回去创建一个对象,每次获取的对象不一样。
<bean name="userService" class="service.UserService" scope="prototype"></bean>
3.每次HTTP请求,Spring容器会根据loginActionbean定义创建一个全新的LoginAction,此仅在当前HTTP Request内有效,而HTTP时无常态的,所以每次的请求,都是心的bean实例,当请求结束,request作用域的bean实例被销毁。
<bean name="userService" class="service.UserService" scope="request"></bean>
4.定义为Session,该作用域仅在基于web的Spring ApplicationContext情形下有效。可以根据需要任意的更改bean的状态。
<bean name="userService" class="service.UserService" scope="session"></bean>
5.Global Session,表示了一个全局的HTTP Session,仅限于全局portlet context的生命周期范围内。
<bean name="userService" class="service.UserService" scope="globalSession"></bean>
Spring Bean的生命周期,完全被容器所管理,从属性设置到各种依赖关系,都是容器负责注入,并进行各个阶段其他事宜的处理,Spring容器为应用开发者定义了清晰的生命周期沟通界面。