`

Spring中的destroy-method方法

 
阅读更多

转载:http://technoboy.iteye.com/blog/970293。destroy-method 欠缺,补上。

 

1. Bean标签的destroy-method方法

配置数据源的时候,会有一个destroy-method方法

Java代码 复制代码 收藏代码
  1. <bean id = "dataSource" class = "org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  2. <property name="driverClassName" value="${jdbc.driver}"></property>
  3. <property name="url" value="${jdbc.url}"></property>
  4. <property name="username" value="${jdbc.username}"></property>
  5. <property name="password" value="${jdbc.password}"></property>
  6. <property name="maxActive" value="${maxActive}"></property>
  7. <property name="maxWait" value="${maxWait}"></property>
  8. <property name="maxIdle" value="30"></property>
  9. <property name="initialSize" value="2"></property>
  10. </bean>
<bean id = "dataSource" class = "org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="${jdbc.driver}"></property>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="maxActive" value="${maxActive}"></property>
		<property name="maxWait" value="${maxWait}"></property>
		<property name="maxIdle" value="30"></property>
		<property name="initialSize" value="2"></property>
</bean>

这个destroy-method属性是干什么用的。什么时候调用呢?
Spring中的doc上是这么说destroy-method方法的---
Java代码 复制代码 收藏代码
  1. The name of the custom destroy method to invoke on bean factory shutdown. The method must have no arguments, but may throw any exception. Note: Only invoked on beans whose lifecycle is under the full control of the factory - which is always the case for singletons, but not guaranteed for any other scope.
The name of the custom destroy method to invoke on bean factory shutdown. The method must have no arguments, but may throw any exception. Note: Only invoked on beans whose lifecycle is under the full control of the factory - which is always the case for singletons, but not guaranteed for any other scope.

其实,这是依赖在Servlet容器或者EJB容器中,它才会被自动给调用的。比如我们用Servlet容器,经常在web.xml文件中配置这样的监听器
Java代码 复制代码 收藏代码
  1. <listener>
  2. <listener-class>
  3. org.springframework.web.context.ContextLoaderListener
  4. </listener-class>
  5. </listener>
<listener>
   <listener-class>
	org.springframework.web.context.ContextLoaderListener
   </listener-class>
</listener>

我们按层次包,看一下ContextLoaderListener这个类。
Java代码 复制代码 收藏代码
  1. public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
  2. //这个是web容器初始化调用的方法。
  3. public void contextInitialized(ServletContextEvent event) {
  4. this.contextLoader = createContextLoader();
  5. if (this.contextLoader == null) {
  6. this.contextLoader = this;
  7. }
  8. this.contextLoader.initWebApplicationContext(event.getServletContext());
  9. }
  10. //这个是web容器销毁时调用的方法。
  11. public void contextDestroyed(ServletContextEvent event) {
  12. if (this.contextLoader != null) {
  13. this.contextLoader.closeWebApplicationContext(event.getServletContext());
  14. }
  15. ContextCleanupListener.cleanupAttributes(event.getServletContext());
  16. }
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
  //这个是web容器初始化调用的方法。
  public void contextInitialized(ServletContextEvent event) {
		this.contextLoader = createContextLoader();
		if (this.contextLoader == null) {
			this.contextLoader = this;
		}
		this.contextLoader.initWebApplicationContext(event.getServletContext());
	}
  
  //这个是web容器销毁时调用的方法。
  public void contextDestroyed(ServletContextEvent event) {
		if (this.contextLoader != null) {
			this.contextLoader.closeWebApplicationContext(event.getServletContext());
		}
		ContextCleanupListener.cleanupAttributes(event.getServletContext());
	}

ContextLoaderListener实现了javax.servlet.ServletContextListener,它是servlet容器的监听器接口。
ServletContextListener接口中定义了两个方法。
Java代码 复制代码 收藏代码
  1. public void contextInitialized(ServletContextEvent event);
  2. public void contextDestroyed(ServletContextEvent event);
public void contextInitialized(ServletContextEvent event);
public void contextDestroyed(ServletContextEvent event);

分别在容器初始化或者销毁的时候调用。
那么当我们销毁容器的时候,其实就是调用的contextDestroyed方法里面的内容。
这里面执行了ContextLoader的closeWebApplicationContext方法。
Java代码 复制代码 收藏代码
  1. public void closeWebApplicationContext(ServletContext servletContext) {
  2. servletContext.log("Closing Spring root WebApplicationContext");
  3. try {
  4. if (this.context instanceof ConfigurableWebApplicationContext) {
  5. ((ConfigurableWebApplicationContext) this.context).close();
  6. }
  7. }
  8. finally {
  9. ClassLoader ccl = Thread.currentThread().getContextClassLoader();
  10. if (ccl == ContextLoader.class.getClassLoader()) {
  11. currentContext = null;
  12. }
  13. else if (ccl != null) {
  14. currentContextPerThread.remove(ccl);
  15. }
  16. servletContext.removeAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  17. if (this.parentContextRef != null) {
  18. this.parentContextRef.release();
  19. }
  20. }
  21. }
public void closeWebApplicationContext(ServletContext servletContext) {
		servletContext.log("Closing Spring root WebApplicationContext");
		try {
			if (this.context instanceof ConfigurableWebApplicationContext) {
				((ConfigurableWebApplicationContext) this.context).close();
			}
		}
		finally {
			ClassLoader ccl = Thread.currentThread().getContextClassLoader();
			if (ccl == ContextLoader.class.getClassLoader()) {
				currentContext = null;
			}
			else if (ccl != null) {
				currentContextPerThread.remove(ccl);
			}
			servletContext.removeAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
			if (this.parentContextRef != null) {
				this.parentContextRef.release();
			}
		}
	}



这里面,将context转型为ConfigurableWebApplicationContext,而
ConfigurableWebApplicationContext继承自ConfigurableApplicationContext,在ConfigurableApplicationContext(ConfigurableApplicationContext实现了Lifecycle,正是前文提到的lifecycle)里有
close()方法的定义。在AbstractApplicationContext实现了close()方法。真正执行的是
Java代码 复制代码 收藏代码
  1. protected void destroyBeans() {
  2. getBeanFactory().destroySingletons();
  3. }
protected void destroyBeans() {
    getBeanFactory().destroySingletons();
}

方法(spring容器在启动的时候,会创建org.apache.commons.dbcp.BasicDataSource的对象,放入singleton缓存中。那么在容器销毁的时候,会清空缓存并调用BasicDataSourc中的close()方法。
)
BasicDataSourc类中的close()方法
Java代码 复制代码 收藏代码
  1. public synchronized void close() throws SQLException {
  2. GenericObjectPool oldpool = connectionPool;
  3. connectionPool = null;
  4. dataSource = null;
  5. try {
  6. if (oldpool != null) {
  7. oldpool.close();
  8. }
  9. } catch(SQLException e) {
  10. throw e;
  11. } catch(RuntimeException e) {
  12. throw e;
  13. } catch(Exception e) {
  14. throw new SQLNestedException("Cannot close connection pool", e);
  15. }
  16. }
public synchronized void close() throws SQLException {
        GenericObjectPool oldpool = connectionPool;
        connectionPool = null;
        dataSource = null;
        try {
            if (oldpool != null) {
                oldpool.close();
            }
        } catch(SQLException e) {
            throw e;
        } catch(RuntimeException e) {
            throw e;
        } catch(Exception e) {
            throw new SQLNestedException("Cannot close connection pool", e);
        }
    }

那么,如果spring不在Servlet或者EJB容器中,我们就需要手动的调用AbstractApplicationContext类中的close()方法,去实现相应关闭的功能。

 

 

分享到:
评论
1 楼 xuezhongyu01 2017-12-19  
博主写的很详细,但最后还是没明白,最后调用BasicDataSourc类中的close()方法的作用是什么

相关推荐

    spring-context-4.2.xsd.zip

    此外,`&lt;bean&gt;`元素还支持通过`init-method`和`destroy-method`属性指定bean的初始化和销毁方法,以进行自定义的生命周期管理。 `spring-context-4.2.xsd`还定义了处理bean作用域(scope)、AOP代理(proxy)、事件...

    spring-jdbc-4.2.xsd.zip

    &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; &lt;!-- 数据源配置 --&gt; &lt;!-- 配置JdbcTemplate --&gt; &lt;bean id="jdbcTemplate" class="org.springframework....

    spring-2.0.8-sources.jar.zip

    2.0.8版本的Bean工厂支持了更丰富的生命周期回调方法,如init-method和destroy-method,使开发者能更好地控制Bean的初始化和销毁过程。 七、JDBC和ORM支持 Spring 2.0.8加强了对JDBC的抽象,提供了JdbcTemplate和...

    架构师面试题系列之Spring面试专题及答案(41题).docx

    init-method 和 destroy-method 是两个非常重要的属性,它们用于指定 Bean 的初始化方法和销毁方法。 init-method 属性用于指定 Bean 的初始化方法,这个方法会在 Bean 实例化完成后被调用。 destroy-method 属性...

    Spring-MyBatis-Ajax重点详解

    Spring 中 ClassPathXmlApplicationContext 是 JavaBean 的工厂,其中 getBean 就是 Spring 提供的工厂方法。 Spring 构造器注入是 Spring 调用有参数构造器创建对象。使用构造器参数标签,实现构造器参数注入:...

    spring-2.5.6源码

    2.5.6版本支持Bean的生命周期回调方法,如初始化方法(init-method)和销毁方法(destroy-method),以及自定义的生命周期处理器。 五、Spring的IoC容器 IoC容器是Spring的核心,负责管理Bean的实例化、配置和组装...

    Spring--2.Spring 中的 Bean 配置-2-1

    - 可以通过`init-method`和`destroy-method`属性指定Bean的初始化和销毁方法,例如: ```xml &lt;bean id="exampleBean" class="com.example.ExampleClass" init-method="init" destroy-method="destroy"/&gt; ``` 7....

    spring笔记

    总的来说,理解Spring配置文件中的bean定义,以及`init-method`、`destroy-method`的使用,对于有效地管理对象的生命周期至关重要。同时,掌握`@ModelAttribute`在Spring MVC中的工作原理,可以帮助我们更高效地进行...

    开源框架spring详解-----spring对JDBC的支持

    &lt;bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; &lt;property name="url" value="jdbc:mysql:///spring" /&gt; ``` 集成第三方连接池后,可以更高效地管理...

    spring-beans

    初始化阶段可以调用`init-method`指定的方法,销毁阶段则调用`destroy-method`指定的方法。此外,Spring提供了多种扩展点,如 BeanPostProcessor 和 InstantiationAwareBeanPostProcessor,允许自定义处理Bean的创建...

    14、加载spring启动首先进入的类方法注解1

    在Spring的XML配置文件中,我们可以使用`init-method`和`destroy-method`属性来指定初始化和销毁的方法。例如: ```xml init-method="init" destroy-method="dostory"/&gt; ``` 这样的配置将会确保在Bean创建时...

    Spring.pdf

    值得注意的是,Spring 2.5版本后引入了注解的方式,可以使用@PostConstruct和@PreDestroy来代替XML中的init-method和destroy-method,从而更简洁地指定Bean的初始化和销毁方法。 容器本身也具备了极高的扩展性,...

    spring-framework-3.2.10.RELEASE 源码

    开发者可以通过实现InitializingBean接口、定义init-method属性、使用@PostConstruct注解来控制初始化,通过 DisposableBean接口、destroy-method属性、@PreDestroy注解来控制销毁。 五、Spring MVC Spring MVC是...

    Spring--2.Spring 中的 Bean 配置-1

    在XML中,可以使用`init-method`和`destroy-method`属性指定。对于注解配置,可以使用`@PostConstruct`和`@PreDestroy`注解。 5. **依赖注入**: Spring的核心特性之一就是依赖注入(Dependency Injection,DI)。它...

    Spring--2.Spring 中的 Bean 配置-3

    此外,Bean的初始化和销毁方法可以使用`init-method`和`destroy-method`属性(在XML中)或`@PostConstruct`和`@PreDestroy`注解(在Java或注解配置中)来定义。这些方法会在Bean生命周期的特定时刻被调用。 最后,...

    基于IDEA的SSH项目之二:配置Spring一---程序包

    &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; ``` 5. **配置事务管理器**:Spring支持声明式事务管理,我们可以在`applicationContext.xml`中配置...

    spring入门学习-3、Bean装配(XML).pdf

    8. **Initialization/destruction method**:初始化与销毁方法,允许用户自定义Bean的生命周期中的初始化和销毁操作。 #### Bean的作用域详解 Bean的作用域定义了Bean的生命周期以及Spring容器如何管理这些Bean的...

    08-IoC配置-bean的生命周期控制

    Spring IOC容器可以管理Bean的生命周期,允许在Bean生命周期的特定点执行定制的任务。 Spring IOC容器对Bean的生命周期...在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法。

    Spring bean初始化及销毁你必须要掌握的回调方法.docx

    在XML配置中,可以通过`destroy-method`属性指定一个销毁方法。在Java配置中,同样可以通过`destroyMethod`属性来指定。 **初始化和销毁顺序** 初始化的顺序如下: 1. 类构造器 2. @PostConstruct注解的方法 3. ...

    Spring配置文件spring-context.zip

    5. `init-method`和`destroy-method`:指定bean初始化和销毁时要调用的方法。 6. `&lt;import&gt;`:引入其他配置文件,方便模块化和复用。 7. `&lt;context:component-scan&gt;`:通过注解扫描特定包下的类,自动发现并注册带...

Global site tag (gtag.js) - Google Analytics