InitializingBean和ApplicationListenerContextRefreshedEvent的用法和区别

本文主要是介绍InitializingBean和ApplicationListenerContextRefreshedEvent的用法和区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.InitializingBean的时机是初始化bean的时候,而ApplicationListener<ContextRefreshedEvent>是在bean初始化完成后。(必须要等到所有的bean都被处理完成之后再进行,必须用InitializingBean

也就是先有InitializingBean,后有ApplicationListener<ContextRefreshedEvent>

InitializingBean初始化bean的顺序是默认构造器->afterPropertiesSet方法

 

2.InitializingBean:作用

spring初始化bean的时候,如果bean实现了InitializingBean接口,

当执行完默认的构造函数之后,就会调用该类实现afterPropertiesSet方法

会自动调用afterPropertiesSet方法。

spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

 

<bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean>

 

import org.springframework.beans.factory.InitializingBean;

public class TestInitializingBean implements InitializingBean{

 

    @Override

    public void afterPropertiesSet() throws Exception {

        System.out.println("ceshi InitializingBean");       

    }

    public void testInit(){

        System.out.println("ceshi init-method");       

    }

没有实现InitializingBean这个接口,直接进行init-method中的,也可以。

<bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean>

import org.springframework.beans.factory.InitializingBean;

public class TestInitializingBean {

    public void testInit(){

        System.out.println("ceshi init-method");       

    }

 

3.ApplicationListener<ContextRefreshedEvent>用法:

一个最简单的方式就是,让我们的bean实现ApplicationListener接口,这样当发布事件时,springioc容器就会以容器的实例对象作为事件源类,并从中找到事件的监听者,此时ApplicationListener接口实例中的onApplicationEvent(ApplicationEvent event)方法就会被调用,我们的逻辑代码就会写在此处。这样我们的目的就达到了。

@Override 

      public void onApplicationEvent(ContextRefreshedEvent event) { 

        if(event.getApplicationContext().getParent() == null){//root application context 没有parent,他就是老大

             //需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。 

        } 

      } 

使用这个必须要有:if(event.getApplicationContext().getParent() == null)或者if(event.getApplicationContext().getParent() != null)这行,代码逻辑必须在这个里面,否不行。非null判断是springmvc管理;null值判断,那里面的逻辑就是spring管理。

 

就需要实现ApplicationListener<ContextRefreshedEvent>接口进行操作,同时,

 

applicationontext和使用MVC之后的webApplicationontext会两次调用上面的方法,如何区分这个两种容器呢?

 

但是这个时候,会存在一个问题,在web 项目中(spring mvc),系统会存在两个容器,一个是root application context ,另一个就是我们自己的 projectName-servlet context(作为root application context的子容器)。

 

这种情况下,就会造成onApplicationEvent方法被执行两次。为了避免上面提到的问题,我们可以只在root application context初始化完成后调用逻辑代码,其他的容器的初始化完成,则不做任何处理,修改后代码

 

 @Override 

      public void onApplicationEvent(ContextRefreshedEvent event) { 

        if(event.getApplicationContext().getParent() == null){//root application context 没有parent,他就是老大

             //需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。 

        } 

 

      } 

 

上面是网上的大部分说法,但是,我在做项目时,我想着为啥不能进行非null值判断呢,那样的话就是projectName-servlet context容器进行管理了,也是可以的呀,后来我一想,原来我的问题实际上是SpringSpringMVC父子 容器的问题,就看这个想要谁管理你的逻辑代码,就用哪个容器,非null

 

判断是springmvc管理;null值判断,那里面的逻辑就是spring管理。这就要求我们必须再看看俩种容器

 

的区别,在这里由于版面问题,不再详述,但是,我会在下一篇文章详细介绍俩种容器的区别与使用,

4.ApplicationListener有自己的用法

所有的类实现ApplicationListener实现这个接口,然后在事件源中调用publishEvent()方法就可以了。(事件三要素)

ApplicationListener,只要有publishEvent,实现ApplicationListener就可以都监听到,其他情况也可以的。比如EventListenter等都可以的。

5.事件:

事件三要素:事件对象、事件监听者、事件源

其实,实现了ApplicationListener这个接口的类就是事件监听者(onApplicationEvent(ApplicationEvent event))。调用了publishEvent(Event event)方法的就是事件源,这个方法中的event就是事件对象。也可以这么说,事件对象和事件监听者就是一个。

IOC的容器的启动过程,当所有的bean都已经处理完成之后,spring ioc容器会有一个发布事件的动作。

 

监听者模式可以自己实现,模仿spring的模式。如果不行,就实现spring监听者接口,抽象出一个模型,然后也就是类似模仿了,就可以实现了。

 

附加结论:监听器、拦截器、过滤器、异步、aop都是横向对代码进行操作,对代码无侵入的操作。

这篇关于InitializingBean和ApplicationListenerContextRefreshedEvent的用法和区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146639

相关文章

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

bytes.split的用法和注意事项

当然,我很乐意详细介绍 bytes.Split 的用法和注意事项。这个函数是 Go 标准库中 bytes 包的一个重要组成部分,用于分割字节切片。 基本用法 bytes.Split 的函数签名如下: func Split(s, sep []byte) [][]byte s 是要分割的字节切片sep 是用作分隔符的字节切片返回值是一个二维字节切片,包含分割后的结果 基本使用示例: pa

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

javascript中break与continue的区别

在javascript中,break是结束整个循环,break下面的语句不再执行了 for(let i=1;i<=5;i++){if(i===3){break}document.write(i) } 上面的代码中,当i=1时,执行打印输出语句,当i=2时,执行打印输出语句,当i=3时,遇到break了,整个循环就结束了。 执行结果是12 continue语句是停止当前循环,返回从头开始。

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository。如果采用原始直接打包放到lib目录的方式进行处理,便对项目的管理带来一些不必要的麻烦。例如版本升级后需要重新打包并,替换原有jar包等等一些额外的工作量和麻烦。为了避免这些不必要的麻烦,通常我们

ActiveMQ—Queue与Topic区别

Queue与Topic区别 转自:http://blog.csdn.net/qq_21033663/article/details/52458305 队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:         1、点对点(point-to-point,简称PTP)Queue消息传递模型:         通过该消息传递模型,一个应用程序(即消息生产者)可以

深入探讨:ECMAScript与JavaScript的区别

在前端开发的世界中,JavaScript无疑是最受欢迎的编程语言之一。然而,很多开发者在使用JavaScript时,可能并不清楚ECMAScript与JavaScript之间的关系和区别。本文将深入探讨这两者的不同之处,并通过案例帮助大家更好地理解。 一、什么是ECMAScript? ECMAScript(简称ES)是一种脚本语言的标准,由ECMA国际组织制定。它定义了语言的语法、类型、语句、

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因