Spring中的实例生成方式及其生命周期
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中的实例生成方式及其生命周期相关的知识,希望对你有一定的参考价值。
三种实例化bean的方式
1.使用类构造器实例化
<!-- 使用类构造器实例化,class属性表示要使用的类的全限定名 --> <bean id="userDao1" class="com.tuniu.dao.daoImpl.UserDaoImpl"> </bean>
使用反射利用类的无参构造器生成实例。
2.使用静态工厂方法实例化
--配置文件:
<!-- 使用静态工厂方法实例化 class属性表示工厂类的全限定名 factory-method属性表示这个工厂类中用于创建实例的静态方法名(必须是static的) --> <bean id="userDao2" class="com.tuniu.dao.StaticDaoFactory" factory-method="createUserDaoInstance"> </bean>
--工厂类:
public class StaticDaoFactory { // 方法必须声明为static的 public static Object createUserDaoInstance() { System.out.println("StaticDaoFactory.createUserDaoInstance()"); return new UserDaoImpl(); } }
3.使用实例化的工厂对象中的方法实例化,首先要构造出工厂实例,然后在生成实例
--配置文件:
<!-- 使用实例化工厂对象中的方法实例化 一、定义工厂bean 二、定义这个bean是由工厂方法创建的,其中: factory-bean属性表示工厂bean的名称(id或name) factory-method属性表示这个工厂类中用于创建实例的方法名(不能是static的) --> <bean id="simpleDaoFactory" class="com.tuniu.dao.SimpleDaoFactory"></bean> <bean id="userDao3" factory-bean="simpleDaoFactory" factory-method="createUserDaoInstance"> </bean>
--工厂类:
public class SimpleDaoFactory { // 方法不能声明为static的 public static Object createUserDaoInstance() { System.out.println("SimpleDaoFactory.createUserDaoInstance()"); return new UserDaoImpl(); } }
我们一般写代码的时候都会分层,显示层,业务层,数据访问层,显示层调用业务层,业务层调用数据访问层。
数据访问层Dao只需要一个实例,业务层Service只需要一个实例,但是action每一次访问都会生成一个实例。
------------
Bean的作用域
在Spring IoC容器中定义的bean默认只有一个实例(单例的),且默认情况下会在容器启动时初始化bean(饿汉式),但我们可以指定Bean节点的lazy-init="true"来延迟初始化bean(懒汉式),这时候,只有第一次获取bean会才初始化bean。如:
--创建类:
public class User { public User() { System.out.println("初始化了User..."); } }
--配置文件:
<!-- scope属性:用于指定bean的生命周期 singleton:单例的,每次ac.getBean()返回的都是同一个实例. prototype:多例的,第次ac.getBean()返回的都是一个新的实例. 默认为singleton。 lazy-init属性:用于指定在什么时候初始化单例的对象 false:表示在创建ApplicationContext时就初始化本单例的对象。 true:表示在第一次调用getBean()获取本对象时才初始化。 默认为default. -->
<bean id="user1" class="com.tuniu.spring.User"/>
或是:
<bean id="user1" class="com.tuniu.spring.User" scope="singleton"/>
或是:
<bean id="user1" class="com.tuniu.spring.User" scope="singleton" lazy-init="default"/>
或是
<bean id="user1" class="com.tuniu.spring.User" scope="singleton" lazy-init="false"/>
以上几种配置,都是在ApplicationContext容器创建时就生成了User对象。
<bean id="user1" class="com.tuniu.spring.User" scope="singleton" lazy-init="true"/>
当lazy-init取值true时,容器创建不会创建User对象,只有在getBean()时才会创建对象,即延迟加载
对所有bean都应用延迟初始化:
方法是在根节点beans中设置属性default-lazy-init="true",如下所示:
<beans default-lazy-init="true" ...>
prototype(原型,表示每次获取的都是新对象)
每次从容器获取bean都是新的对象。
<bean id="user1" class="com.tuniu.spring.User" scope="prototype"/>
getBean()时生成实例。
指定Bean的初始化方法和销毁方法
--创建类:
public class UserDao { private DataSource dataSource; public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } /** * 初始化方法 */ public void init() { System.out.println("UserDao.init() 初始化方法"); } /** * 销毁的方法 */ public void destroy() { System.out.println("UserDao.destroy() 销毁的方法"); } }
--配置:
<!-- 单例的对象,配置了初始化方法与销毁方法 --> <bean id="userDao" class="com.tuniu.spring.UserDao" init-method="init" destroy-method="destroy" />
--测试代码:
// 在ApplicationContext接口中没有定义close()方法,要想调用,就得先转为子类类型才行。 // 一定要关闭ApplicationContext,给bean配置的销毁方法才会被调用。 // 在单例时,配置的初始化与销毁方法都会被调用。 // 在多例时,只有配置的初始化才会被调用。 @Test public void test() throws Exception { ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml", getClass()); UserDao userDao = (UserDao) ac.getBean("userDao"); System.out.println(userDao); ac.close(); }
--注意:
---如果scope属性为prototype则不受spring缓存的控制,destory方法也将不会执行(scope调为singleton时才会有效)。
---要调用ApplicationContext的close()方法才会执行destory方法(在ApplicationContext接口中没有close()方法,需要强转为具体的实现类才可以调用)
以上是关于Spring中的实例生成方式及其生命周期的主要内容,如果未能解决你的问题,请参考以下文章
Spring02——Spring 中 Bean 的生命周期及其作用域