当前位置: 首页 > news >正文

公众号和网站先做哪个wordpress the7 慢

公众号和网站先做哪个,wordpress the7 慢,上海景点排名前十,图书网站开发背景Java 事件/监听器编程模型 设计模式-观察者模式的拓展 可观察者对象(消息发送者) Java.util.Observalbe观察者 java.util.Observer 标准化接口(标记接口) 事件对象 java.util.EventObject事件监听器 java.util.EventListener public class ObserverDemo {public static vo…

Java 事件/监听器编程模型

设计模式-观察者模式的拓展

  • 可观察者对象(消息发送者) Java.util.Observalbe
  • 观察者 java.util.Observer

标准化接口(标记接口)

  • 事件对象 java.util.EventObject
  • 事件监听器 java.util.EventListener
public class ObserverDemo {public static void main(String[] args) {Observable observable = new EventObservable();observable.addObserver(new EventObserver());observable.notifyObservers("hello");}/*** 因为我们要调用 change 监听者这个方法才能生效 但是这个方法是个protected 所以我们进行拓展* */static class EventObservable extends Observable {public void setChanged(){super.setChanged();}public void notifyObservers(Object args) {setChanged();super.notifyObservers(new EventObject(args));clearChanged();}}static class EventObserver implements Observer, EventListener {@Overridepublic void update(Observable o, Object event) {EventObject eventObject = (EventObject) event;System.out.println("收到消息:" + eventObject);}}
}

理解:
发布事件的是被监听的对向,里面会注册监听器,也就是需要感知当前对象变化的对象。
JDKEventListener提供了这个标记接口,算是一种规范,表名这个是事件的监听器。
EventObject 这个也算是一个标准,这个对象是方便数据在事件发布的时候进行传递。

面向接口的事件/监听器设计模式

在这里插入图片描述
基本模式:
一般监听器会继承EventListener
一般事件会继承EventObject

面向注解的事件/监听器设计模式

在这里插入图片描述

Spirng 标准事件 ApplicationEvent

在这里插入图片描述

基于接口的事件监听器

在这里插入图片描述

public static void main(String[] args) {GenericApplicationContext context = new GenericApplicationContext();// 注册一个事件监听context.addApplicationListener(new ApplicationListener<ApplicationEvent>() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println(event.getTimestamp() + "接收到事件 : " + event);}});context.refresh();context.close();
}

可以看到这里收到了两个事件,那么事件从哪里发布的呢?请看事件发布器。
在这里插入图片描述

基于注解的事件监听器

在这里插入图片描述

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(ApplicatonListenrDemo.class);context.refresh();context.close();
}
@EventListener
public void onApplicationEvent(ApplicationEvent applicationEvent) {System.out.println(applicationEvent);
}
// 这样的话就会分类别来处理
@EventListener
public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {System.out.println(applicationEvent + "re");
}
// 异步处理
@EnableAsync
public class ApplicatonListenrDemo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(ApplicatonListenrDemo.class);context.refresh();context.close();}@EventListenerpublic void onApplicationEvent(ApplicationEvent applicationEvent) {System.out.println(applicationEvent);}@EventListenerpublic void onApplicationEvent(ContextRefreshedEvent applicationEvent) {System.out.println(applicationEvent + "re");}@EventListener@Asyncpublic void onApplicationEvent(ContextClosedEvent applicationEvent) {System.out.println(applicationEvent);System.out.println(Thread.currentThread().getId());}
}
// 控制顺序
public class ApplicatonListenrDemo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(ApplicatonListenrDemo.class);context.refresh();context.close();}@EventListener@Order(2)public void onApplicationEvent2(ContextRefreshedEvent applicationEvent) {System.out.println("=======");}@EventListener@Order(1)public void onApplicationEvent1(ContextRefreshedEvent applicationEvent) {System.out.println("****");}
}

注册Spirng ApplicationListenner

方法一: ApplicationListener 作为SpirngBean注册

context.register(MyEventListener.class);
static class MyEventListener implements ApplicationListener<ApplicationEvent> {@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println("=====>");}
}

方法二:通过ConfigrableApplicationContextAPI 注册

context.addApplicationListener(new ApplicationListener<ApplicationEvent>() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println(event.getTimestamp() + "接收到事件 : " + event);}
});

事件发布器

在这里插入图片描述

public class ApplicatonListenrDemo implements ApplicationEventPublisherAware {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(ApplicatonListenrDemo.class);context.refresh();context.start();context.close();}@EventListenerpublic void onApplicationEvent(ApplicationEvent event) {System.out.println(event);}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {applicationEventPublisher.publishEvent(new ApplicationEvent("hello") {});// 发布任意对象 重载方法applicationEventPublisher.publishEvent("yes");}
}

事件发布器如何找到对应的监听器进行实事件的发布呢? 在发布时间的时候会查缓存,缓存如果没有对应的监听器,则会更具事件泛型类型进行判断。
在这里插入图片描述
根据事件的泛型类型进行判断,如果类型符合加入监听器数组。
在这里插入图片描述

Spring 事件传播

在这里插入图片描述

public static void main(String[] args) {// 1 创建 parent Spring 应用上下文AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();parent.setId("parent");parent.register(Mylistener.class);// 创建current spring 应用上下文AnnotationConfigApplicationContext current = new AnnotationConfigApplicationContext();current.setId("current");current.register(Mylistener.class);current.setParent(parent);// current parentparent.refresh();current.refresh();parent.close();current.close();}
static class Mylistener implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {System.out.printf("监听到应用上下文[ID %s]\n", event.getApplicationContext().getId());}
}

第一个事件触发是parent,第二,三个由于事件传播子和父都触发了这个事件:
在这里插入图片描述

原理就是,源码会在父也发布事件:
在这里插入图片描述
如何避免:

public class HierachicalEventDemo {public static void main(String[] args) {// 1 创建 parent Spring 应用上下文AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();parent.setId("parent");parent.register(Mylistener.class);// 创建current spring 应用上下文AnnotationConfigApplicationContext current = new AnnotationConfigApplicationContext();current.setId("current");current.register(Mylistener.class);current.setParent(parent);// current parentparent.refresh();current.refresh();parent.close();current.close();}static class Mylistener implements ApplicationListener<ContextRefreshedEvent> {/*** 这里之所以要静态是因为我们在 parent 和 current 是不是一样的对象 也就是有两对象* 但是静态字段就是类共用的* 如果时间发布过不再重新发布*/private static Set<ApplicationEvent> processedEvents = new LinkedHashSet();@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {if (processedEvents.add(event)) {System.out.printf("监听到应用上下文[ID %s] %s\n ", event.getApplicationContext().getId(), event);}}}
}

Spirng 内建事件

在这里插入图片描述

Spring Payload 事件

在这里插入图片描述使用的时候不能简单继承使用,发送方法最好是用object这个方法。

自定义Spirng事件

在这里插入图片描述

public class MyEvent extends ApplicationEvent {public MyEvent(String msg) {super(msg);}@Overridepublic String getSource() {return (String) super.getSource();}public String getMessage() {return getSource();}
}
public class MyListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println(event.getMessage());}
}
public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(Mylistener.class);context.refresh();context.publishEvent(new MyEvent("test event"));context.close();}
}

事件发布注入

ApplicationEventPublisherAwae 回调接口
通过@Autowired ApplicationEventPublisher

依赖查找

在这里插入图片描述
在这里插入图片描述

ApplicationEventMulticaster的底层实现

在这里插入图片描述
AbstractContext事件分发布是通过ApplicationEventMulticaster来实现的:
在这里插入图片描述

同步和异步Spirng事件广播

在这里插入图片描述
如果是异步如果要设置Executeor 是需要类型转换的,不是基于接口的编程方式。

public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(Mylistener.class);context.refresh();ApplicationEventMulticaster multicaster = context.getBean(ApplicationEventMulticaster.class);if (multicaster instanceof SimpleApplicationEventMulticaster) {ExecutorService executor = newSingleThreadExecutor();SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = (SimpleApplicationEventMulticaster) multicaster;simpleApplicationEventMulticaster.setTaskExecutor(executor);// 优雅的关闭线程池simpleApplicationEventMulticaster.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {@Overridepublic void onApplicationEvent(ContextClosedEvent event) {if (!executor.isShutdown()) {executor.shutdown();}}});}context.publishEvent(new MyEvent("test event"));context.close();}
}

通过注解的方式实现:

@EnableAsync
public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(Demo.class);context.refresh();context.publishEvent(new MyEvent("test event"));context.close();}@EventListener@Asyncpublic void onApplicationContext(ApplicationEvent event) {System.out.println(Thread.currentThread().getName() +  event);}// 这是自定义我们的线程池@BeanExecutor taskExecutor() {return Executors.newSingleThreadExecutor();}
}

事件的异常情况

在这里插入图片描述

public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(Demo.class);context.refresh();ApplicationEventMulticaster multicaster = context.getBean(ApplicationEventMulticaster.class);if (multicaster instanceof SimpleApplicationEventMulticaster) {SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = (SimpleApplicationEventMulticaster) multicaster;simpleApplicationEventMulticaster.setErrorHandler((t) ->{System.out.printf("发生了异常" );});}context.publishEvent(new MyEvent("test event"));context.close();}@EventListenerpublic void onApplicationContext(ContextClosedEvent event) {System.out.println(Thread.currentThread().getName() +  event);throw new RuntimeException("制造异常");}@BeanExecutor taskExecutor() {return Executors.newSingleThreadExecutor();}
}

Spirng 事件/监听实现原理

在这里插入图片描述
在这里插入图片描述
ListenerRetriever 会过滤对应的ApplicationListener Event实例 这个Event实例包括它本身及它的孙子类
在这里插入图片描述
处理泛型并过滤:
在这里插入图片描述
在处理事件的时候就会去获取对应的监听器:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
参考资料:小马哥核心编程思想。

http://www.15wanjia.com/news/194361.html

相关文章:

  • 不同企业的网络营销网站文山州住房建设网站
  • 红色页面网站网上电商
  • 网站开发者账号购买郑州国外网站建设
  • 网站反向链接浏览器打开网址404
  • 做水利网站需要多少钱企业请别人做网站
  • 做的比较好的企业网站网站空间排行榜
  • 做网站是怎么赚钱的违法网站开发文本模版
  • 设计师常去的素材网站在国内做推广产品用什么网站好
  • 怎样在手机上做网站金融网站设计欣赏
  • 河北省企业网站建设公司中装建设虎哥
  • 网站建设具体工作有什么滕州营销型网站
  • 企业网站建设公司网络服务西安大型网站设计公司
  • 企业网站建设的要素红网
  • 搜狐网站开发郑州防控升级
  • 东莞网站建设图表h5制作工具手机版
  • 建设局网站打不开是什么原因策划平台
  • 一个网站做十个二级域名项目交流平台
  • 二手商品网站制作wordpress链接前面的图标
  • 网站怎么做舆情监测建设厅电工证查询网站官方网
  • 如何经营一个购物网站wordpress 好用的编辑器
  • 品牌网站官网如何注册免费企业邮箱
  • 扫描购物网站建设海南网站设计公司
  • 网站建设登录结构图浙江网站建设上市公司
  • 微课做动画的网站本地搭建网站
  • 站长之家html模板wordpress菜单移到右边
  • 网站优化怎么做赚钱软件哪个赚钱多又快
  • 有什么可以在线做奥数题的网站陈巴尔虎旗网站建设
  • 铁岭 网站建设百度指数分是什么
  • 自己的电脑做网站服务器 买的服务器 速度必应搜索引擎网址
  • 生活服务类网站开发前端入职后很痛苦