本文主要是介绍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接口,这样当发布事件时,spring的ioc容器就会以容器的实例对象作为事件源类,并从中找到事件的监听者,此时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容器进行管理了,也是可以的呀,后来我一想,原来我的问题实际上是Spring和SpringMVC父子 容器的问题,就看这个想要谁管理你的逻辑代码,就用哪个容器,非null
判断是springmvc管理;null值判断,那里面的逻辑就是spring管理。这就要求我们必须再看看俩种容器
的区别,在这里由于版面问题,不再详述,但是,我会在下一篇文章详细介绍俩种容器的区别与使用,
4.ApplicationListener有自己的用法
所有的类实现ApplicationListener实现这个接口,然后在事件源中调用publishEvent()方法就可以了。(事件三要素)
ApplicationListener,只要有publishEvent,实现ApplicationListener就可以都监听到,其他情况也可以的。比如Event,Listenter等都可以的。
5.事件:
事件三要素:事件对象、事件监听者、事件源
其实,实现了ApplicationListener这个接口的类就是事件监听者(onApplicationEvent(ApplicationEvent event))。调用了publishEvent(Event event)方法的就是事件源,这个方法中的event就是事件对象。也可以这么说,事件对象和事件监听者就是一个。
在IOC的容器的启动过程,当所有的bean都已经处理完成之后,spring ioc容器会有一个发布事件的动作。
监听者模式可以自己实现,模仿spring的模式。如果不行,就实现spring监听者接口,抽象出一个模型,然后也就是类似模仿了,就可以实现了。
附加结论:监听器、拦截器、过滤器、异步、aop都是横向对代码进行操作,对代码无侵入的操作。
这篇关于InitializingBean和ApplicationListenerContextRefreshedEvent的用法和区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!