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

相关文章

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华

python3 gunicorn配置文件的用法解读

《python3gunicorn配置文件的用法解读》:本文主要介绍python3gunicorn配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python3 gunicorn配置文件配置文件服务启动、重启、关闭启动重启关闭总结python3 gun

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(

C#中DrawCurve的用法小结

《C#中DrawCurve的用法小结》本文主要介绍了C#中DrawCurve的用法小结,通常用于绘制一条平滑的曲线通过一系列给定的点,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 如何使用 DrawCurve 方法(不带弯曲程度)2. 如何使用 DrawCurve 方法(带弯曲程度)3.使用Dr

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

pytorch之torch.flatten()和torch.nn.Flatten()的用法

《pytorch之torch.flatten()和torch.nn.Flatten()的用法》:本文主要介绍pytorch之torch.flatten()和torch.nn.Flatten()的用... 目录torch.flatten()和torch.nn.Flatten()的用法下面举例说明总结torch

Python Faker库基本用法详解

《PythonFaker库基本用法详解》Faker是一个非常强大的库,适用于生成各种类型的伪随机数据,可以帮助开发者在测试、数据生成、或其他需要随机数据的场景中提高效率,本文给大家介绍PythonF... 目录安装基本用法主要功能示例代码语言和地区生成多条假数据自定义字段小结Faker 是一个 python