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

相关文章

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

mysql中insert into的基本用法和一些示例

《mysql中insertinto的基本用法和一些示例》INSERTINTO用于向MySQL表插入新行,支持单行/多行及部分列插入,下面给大家介绍mysql中insertinto的基本用法和一些示例... 目录基本语法插入单行数据插入多行数据插入部分列的数据插入默认值注意事项在mysql中,INSERT I

Before和BeforeClass的区别及说明

《Before和BeforeClass的区别及说明》:本文主要介绍Before和BeforeClass的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Before和BeforeClass的区别一个简单的例子当运行这个测试类时总结Before和Befor

mapstruct中的@Mapper注解的基本用法

《mapstruct中的@Mapper注解的基本用法》在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper),本文给大家介绍ma... 目录1. 基本用法2. 常用属性3. 高级用法4. 注意事项5. 总结6. 编译异常处理在MapSt

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

MyBatis ResultMap 的基本用法示例详解

《MyBatisResultMap的基本用法示例详解》在MyBatis中,resultMap用于定义数据库查询结果到Java对象属性的映射关系,本文给大家介绍MyBatisResultMap的基本... 目录MyBATis 中的 resultMap1. resultMap 的基本语法2. 简单的 resul

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

java中Optional的核心用法和最佳实践

《java中Optional的核心用法和最佳实践》Java8中Optional用于处理可能为null的值,减少空指针异常,:本文主要介绍java中Optional核心用法和最佳实践的相关资料,文中... 目录前言1. 创建 Optional 对象1.1 常规创建方式2. 访问 Optional 中的值2.1

git stash命令基本用法详解

《gitstash命令基本用法详解》gitstash是Git中一个非常有用的命令,它可以临时保存当前工作区的修改,让你可以切换到其他分支或者处理其他任务,而不需要提交这些还未完成的修改,这篇文章主要... 目录一、基本用法1. 保存当前修改(包括暂存区和工作区的内容)2. 查看保存了哪些 stash3. 恢

Python struct.unpack() 用法及常见错误详解

《Pythonstruct.unpack()用法及常见错误详解》struct.unpack()是Python中用于将二进制数据(字节序列)解析为Python数据类型的函数,通常与struct.pa... 目录一、函数语法二、格式字符串详解三、使用示例示例 1:解析整数和浮点数示例 2:解析字符串示例 3:解