关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种:
第一种:通过注解@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class DataInitializer{ @PostConstruct public void initMethod() throws Exception { System.out.println("initMethod 被执行"); } @PreDestroy public void destroyMethod() throws Exception { System.out.println("destroyMethod 被执行"); } }
第二种是:通过 在xml中定义init-method 和 destory-method方法
public class DataInitializer{ public void initMethod() throws Exception { System.out.println("initMethod 被执行"); } public void destroyMethod() throws Exception { System.out.println("destroyMethod 被执行"); } }
<bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>
第三种是: 通过bean实现InitializingBean和 DisposableBean接口
import org.springframework.beans.factory.DisposableBean; public class DataInitializer implements InitializingBean,DisposableBean{ @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet 被执行"); } @Override public void destroy() throws Exception { System.out.println("destroy 被执行"); } }
其中第一种和第二种是同一种形式,只不过一种xml配置,另外一种采用注解形式罢了,有很大区别的是第三种,如果同一个bean同时采用两种方式初始化的时候执行某个方法,首先在执行顺序上就会体现出来。
先执行afterPropertiesSet(),后执行initMethod()
这里我们看下源码
这方式在spring中是怎么实现的?
通过查看spring的加载bean的源码类(AbstractAutowireCapableBeanFactory)可看出其中奥妙
AbstractAutowireCapableBeanFactory类中的invokeInitMethods讲解的非常清楚,源码如下:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { //判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法 boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { //直接调用afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); return null; } },getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //直接调用afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现 invokeCustomInitMethod(beanName, bean, mbd); } }
总结:
1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用
2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖
3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
主要内容:Linux手工启动进程,Linux调度启动进程在 Linux 系统中,每个进程都有一个唯一的进程号(PID),方便系统识别和调度进程。通过简单地输出运行程序的程序名,就可以运行该程序,其实也就是启动了一个进程。 总体来说,启动一个进程主要有 2 种途径,分别是通过手工启动和通过调度启动(事先进行设置,根据用户要求,进程可以自行启动),接下来就一一介绍这 2 中方式。 Linux手工启动进程 手工启动进程指的是由用户输入命令直接启动一个进程,根
本文向大家介绍Python的几种主动结束程序方式,包括了Python的几种主动结束程序方式的使用技巧和注意事项,需要的朋友参考一下 对于如何结束一个Python程序或者用Python操作去结束一个进程等,Python本身给出了好几种方法,而这些方式也存在着一些区别,对相关的几种方法看了并实践了下,同时也记录下。 参考: Python 核心编程(第二版) http://www.zhihu.com/q
本文向大家介绍调试PHP程序的多种方法介绍,包括了调试PHP程序的多种方法介绍的使用技巧和注意事项,需要的朋友参考一下 调试的定义:通过一定方法,在程序中找到并减少缺陷的数量,从而使其能正常工作。 这里说一些如何调试PHP程序的经验。 一、PHP自带的调试功能 1、自带的报错功能 两个名词:开发环境是开发人员在进行开发和调试的环境,生产环境是最终客户在用的线上环境; 开发环境和生产环境要分开设置报
本文向大家介绍Java线程池的几种实现方法和区别介绍,包括了Java线程池的几种实现方法和区别介绍的使用技巧和注意事项,需要的朋友参考一下 Java线程池的几种实现方法和区别介绍 使用:LinkedBlockingQueue实现线程池讲解 关于:RejectedExecutionHandler几种默认实现讲解 以上这篇Java线程池的几种实现方法和区别介绍就是小编分享给大家的全部内容了,希望能给大
我正在为WildFly创建一个web应用程序,它将通过JPA(Hibernate)连接到一个MySQL数据库。目前,我只是尝试让WildFly在独立模式下启动并加载MySQL驱动程序。我将此页面作为指南:http://wildfly.org/news/2014/02/06/glassfish-to-wildfly-migration/ Windows 7 Enterprise SP1 Oracle
我正在处理Spring Boot项目,突然遇到应用程序无法加载MySQL jdbc的问题。(我编译了一次这个项目,没有改变任何东西) 这是我的pom.xml: 这是我的application.properties: Logcat: MySQL数据库最初是使用hibernate创建的。这些配置工作正常,但我不确定这里的真正问题是什么 编辑:我删除了。m2文件夹并从一开始安装所有依赖项。
本文向大家介绍PHP读取大文件的几种方法介绍,包括了PHP读取大文件的几种方法介绍的使用技巧和注意事项,需要的朋友参考一下 读取大文件一直是一个头痛的问题,我们像使用php开发读取小文件可以直接使用各种函数实现,但一到大文章就会发现常用的方法是无法正常使用或时间太长太卡了,下面我们就一起来看看关于php读取大文件问题解决办法,希望例子能帮助到各位。 场景:PHP读取超大文件,例如1G的日志文件,我
本文向大家介绍Linux启动新进程的三种方法,包括了Linux启动新进程的三种方法的使用技巧和注意事项,需要的朋友参考一下 程序中,我们有时需要启动一个新的进程,来完成其他的工作。 下面介绍了三种实现方法,以及这三种方法之间的区别。 1.system函数-调用shell进程,开启新进程 system函数,是通过启动shell进程,然后执行shell命令进程。 原型: int system(cons