spring 事物监听机制,同步异步处理
来源:互联网 发布:心理测试 软件 编辑:程序博客网 时间:2024/06/07 09:22
一、概念原理:
- SUBJECT
- 目标知道它的观察者。可以有任意多个观察者观察同一个目标。
- 提供注册和删除观察者对象的接口。
- Observer(观察者)
- 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
- ConcreteSubject(具体目标)
- 将有关状态存入各ConcreteObserver对象。
- 当它的状态发生改变时,向它的各个观察者发出通知。
- ConcreteObserver(具体观察者)
- 维护一个指向ConcreteSubject对象的引用。
- 存储有关状态,这些状态应与目标的状态保持一致。
- 实现Observer的更新接口以使自身状态与目标的状态保持一致。
实现一个事件监听需要三个步骤:创建一个事件ApplicationEvent用来定义自己需要的事件,创建一个ApplicationListener用来监听并处理发布的事件, 用spring的应用上下文 ApplicationContext 来 publish发布 一个事件。
什么是ApplicationContext?
它是spring的核心,Context我们通常解释为上下文环境,但是理解成容器会更好些。
ApplicationContext则是应用的容器。
Spring把Bean(object)放在容器中,需要用就通过get方法取出来。
ApplicationEvent
是个抽象类,里面只有一个构造函数和一个长整型的timestamp。
ApplicationListener
是一个接口,里面只有一个onApplicationEvent方法。
所以自己的类在实现该接口的时候,要实装该方法。
如果在上下文中部署一个实现了ApplicationListener接口的bean,
那么每当在一个ApplicationEvent发布到 ApplicationContext时,
这个bean得到通知。其实这就是标准的Oberver设计模式。
1、创建事件ApplicationEvent:
public class FileEnvent extends ApplicationEvent { private static final long serialVersionUID = 1L; String filePath; public FileEnvent(Object source, String filePath) { super(source); this.filePath = filePath; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; }}
注意:这里需要继承ApplicationEvent ,不过Spring也提供了几个内置事件:
1、 ContextRefreshedEvent:ApplicationContext容器初始化或者刷新时触发该事件。
2、 ContextStartedEvent:当使用ConfigurableApplicationContext接口的start()方法启动ApplicationContext容器时触发该事件。
3、 ContextClosedEvent:当使用ConfigurableApplicationContext接口的close()方法关闭ApplicationContext容器时触发该事件。
4、 ContextStopedEvent: 当使用ConfigurableApplicationContext接口的stop()方法停止ApplicationContext容器时触发该事件。
2、创建监听器ApplicationListener:
@Componentpublic class FileListener implements ApplicationListener<ApplicationEvent>{
@Override public void onApplicationEvent(ApplicationEvent event) { if(event instanceof FileEnvent){ FileEnvent fileEnvent = (FileEnvent) event; System.out.println( "file path is:" + event.getFilePath());
} }
}3、获取ApplicationContext:
@Componentpublic class FileApplicationContext implements ApplicationContextAware { private static ApplicationContext ctx; @SuppressWarnings("static-access") @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.ctx = applicationContext; } public static ApplicationContext getCtx() { return ctx; }}这里通过继承ApplicationContextAware来获得ApplicationContext,当然,这个类也需要加载为spring,通过注解和配置文件配置都可以,
这里用注解也是为了解耦。
注意:这里有两个问题:
1)需要使用注解@Component 加载为spring的容器,也可以在配置文件里面配置,这里用注解是为了和配置文件解耦。
2)用@Component 会有两次执行onApplicationEvent()方法的可能,解决onApplicationEvent(方法被执行两次以上的问题:
原因:
在web 项目中(spring mvc),系统会存在两个容器,一个是root application context ,另一个就是我们自己的 projectName-servlet context(作为root application context的子容器)。 这种情况下,就会造成onApplicationEvent方法被执行两次。
解决方法:
1.需要注意的是,把@Component 改为@Controller,这样才表示是一个Spring的Bean(否则在相关Spring的xml中配置),才能被Spring容器处理。
2.若是web项目则可通过ContextLoader.getCurrentWebApplicationContext();方法来获取上下文容器。
上面获取ApplicationContext可以改成下面的实现:
public class WebContextUtil {
private static WebApplicationContext wac;public synchronized static WebApplicationContext getContext() {if( null == wac ) {wac = ContextLoader.getCurrentWebApplicationContext();}return wac;}}
4、发布事件:
public static void main(){FileEnvent fileEnvent = new FileEnvent("", filePath); WebContextUtil.getContext().publishEvent(fileEnvent);}
若不是web项目,可以用下面的方法,但是记得监听器用@Controller注解或在配置文件里面配置监听器
public static void main(){FileEnvent fileEnvent = new FileEnvent("", filePath);
FileApplicationContext .getCtx().publishEvent(fileEnvent);}
注意上面的ApplicationListener 中的监听机制为同步执行,即若发布两个事件,则必须等待前一个事件完成才能继续执行下一个事件,这里可以通过
<!-- 任务执行器 --> <task:executor id="executor" pool-size="10"/><!--开启注解调度支持 @Async @Scheduled--> <task:annotation-driven executor="executor" proxy-target-class="true"/>
2、在监听方法加上注解即可实现异步调用
@Componentpublic class FileListener implements ApplicationListener<ApplicationEvent>{@Async @Override public void onApplicationEvent(ApplicationEvent event) { if(event instanceof FileEnvent){ FileEnvent fileEnvent = (FileEnvent) event; System.out.println( "file path is:" + event.getFilePath()); } }}
通过以上方法即可实现同步或者异步的事件监听机制,非常实用。
部分内容参考:http://blog.csdn.net/sd0902/article/details/8394082
- spring 事物监听机制,同步异步处理
- spring 事物处理机制
- PHP事物处理机制
- Spring 事物机制总结
- Spring 事物机制总结
- Spring 事物机制总结
- Spring 事物机制总结
- Spring 事物机制总结
- Spring 事物机制总结
- Spring 事物机制总结
- spring事物传播机制
- Spring事物传播机制
- Spring 事物机制总结
- Spring 事物处理2
- spring事物处理
- spring事物处理
- Spring 事物处理
- Spring事物处理
- 剑指offer——合并两个排序的链表__
- 搬运工整理之HoloLens你的一个HoloLens应用程序 02
- lucene操作
- TensorFlow在Windows环境下的搭建
- codeforces811C——Vladik and Memorable Trip(动态规划)
- spring 事物监听机制,同步异步处理
- OpenTSDB 安装 启动 数据存储
- JSON 字符串 与 java 对象的转换
- 自动化测试2
- java内部类学习
- 谈谈我对Linux系统学习的历程回顾
- java中的Timer用法(三) 似乎可以使用了,可以上线了
- DSP笔记
- hadoop.zookeeper.hbase的hbase中master和regionserver无法启动