深入了解Spring中Bean的作用域和生命周期
作用域的种类
Spring容器在初始化一个Bean的实例时,同时会指定该实例的作用域。Spring3为Bean定义了五种作用域,具体如下。
1)singleton
单例模式,使用singleton定义的Bean在Spring容器中只有一个实例,这也是Bean默认的作用域。
2)prototype
原型模式,每次通过Spring容器获取prototype定义的Bean时,容器都将创建一个新的Bean实例。
3)request
在一次HTTP请求中,容器会返回该Bean的同一个实例。而对不同的HTTP请求,会返回不同的实例,该作用域仅在当前HTTPRequest内有效。
4)session
在一次HTTPSession中,容器会返回该Bean的同一个实例。而对不同的HTTP请求,会返回不同的实例,该作用域仅在当前HTTPSession内有效。
5)globalSession
在一个全局的HTTPSession中,容器会返回该Bean的同一个实例。该作用域仅在使用portletcontext时有效。
在上述五种作用域中,singleton和prototype是最常用的两种,接下来将对这两种作用域进行详细讲解。
singleton作用域
singleton是Spring容器默认的作用域,当一个Bean的作用域为singleton时,Spring容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义相匹配,就只会返回Bean的同一个实例。
通常情况下,这种单例模式对于无会话状态的Bean(如DAO层、Service层)来说,是最理想的选择。
在Spring配置文件中,可以使用
在项目的src目录下创建一个名为com.mengma.scope的包,在该包下创建Person类,类中不需要添加任何成员,然后创建Spring的配置文件applicationContext.xml,将上述Bean的定义方式写入配置文件中,最后创建一个名为PersonTest的测试类,编辑后如下所示。
packagecom.mengma.scope; importorg.junit.Test; importorg.springframework.context.ApplicationContext; importorg.springframework.context.support.ClassPathXmlApplicationContext; publicclassPersonTest{ @Test publicvoidtest(){ //定义Spring配置文件路径 StringxmlPath="com/mengma/scope/applicationContext.xml"; //初始化Spring容器,加载配置文件,并对bean进行实例化 ApplicationContextapplicationContext=newClassPathXmlApplicationContext( xmlPath); //输出获得实例 System.out.println(applicationContext.getBean("person")); System.out.println(applicationContext.getBean("person")); } }
使用JUnit测试运行test()方法,运行成功后,控制台的输出结果如图1所示。
从图1中可以看到,两次输出的结果相同,这说明Spring容器只创建了一个Person类的实例。由于Spring容器默认作用域是singleton,如果不设置scope="singleton",则其输出结果也将是一个实例。
prototype作用域
使用prototype作用域的Bean会在每次请求该Bean时都会创建一个新的Bean实例。因此对需要保持会话状态的Bean(如Struts2的Action类)应该使用prototype作用域。
在Spring配置文件中,要将Bean定义为prototype作用域,只需将
将《singleton作用域》部分中的配置文件更改成上述代码形式后,再次运行test()方法,控制台的输出结果如图2所示。
从图2的输出结果中可以看到,两次输出的结果并不相同,这说明在prototype作用域下,Spring容器创建了两个不同的Person实例。
生命周期
而对于prototype作用域的Bean,Spring只负责创建,当容器创建了Bean的实例后,Bean的实例就交给客户端代码管理,Spring容器将不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会创建一个新的实例,并且不会管那些被配置成prototype作用域的Bean的生命周期。
了解Spring生命周期的意义就在于,可以利用Bean在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在Bean被初始化后和被销毁前执行一些相关操作。
在Spring中,Bean的生命周期是一个很复杂的执行过程,我们可以利用Spring提供的方法定制Bean的创建过程。
当一个Bean被加载到Spring容器时,它就具有了生命,而Spring容器在保证一个Bean能够使用之前,会进行很多工作。Spring容器中Bean的生命周期流程如图3所示。
Bean生命周期的整个执行过程描述如下。
1)根据配置情况调用Bean构造方法或工厂方法实例化Bean。
2)利用依赖注入完成Bean中所有属性值的配置注入。
3)如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值。
4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()方法传入当前工厂实例的引用。
5)如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用。
6)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialzation()对Bean进行加工操作,此处非常重要,Spring的AOP就是利用它实现的。
7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。
8)如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法。
9)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialization()。此时,Bean已经可以被应用系统使用了。
10)如果在
11)如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean销毁;如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法对Bean进行销毁。
Spring为Bean提供了细致全面的生命周期过程,通过实现特定的接口或
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。