您的位置:首页 > 游戏 > 游戏 > 什么是网络营销中的免费营销策略_网络营销论文2500字_网络安全培训机构哪家好_最近国际新闻大事

什么是网络营销中的免费营销策略_网络营销论文2500字_网络安全培训机构哪家好_最近国际新闻大事

2025/7/15 21:46:41 来源:https://blog.csdn.net/qq_44818304/article/details/146958582  浏览:    关键词:什么是网络营销中的免费营销策略_网络营销论文2500字_网络安全培训机构哪家好_最近国际新闻大事
什么是网络营销中的免费营销策略_网络营销论文2500字_网络安全培训机构哪家好_最近国际新闻大事

简介

spring提供的事件机制:用户编写监听器,监听某个类型的事件,在另一端,用户调用spring提供的API,发布某个类型的事件,spring会遍历所有的监听器,寻找能够处理事件的监听器,然后调用它来处理事件,这就是spring提供的事件机制。

使用案例

第一步:事件对象,它主要负责存储事件相关的数据

public class MyEvent extends ApplicationEvent {public MyEvent(Object source) {super(source);System.out.println("MyEvent, 事件对象初始化, 事件信息:" + source);}
}

第二步:监听器,有两种创建方式,一种是实现ApplicationListener接口,一种是使用@EventListener注解

// 第一种方式:ApplicationListener接口
@Component
public class MyAppListener implements ApplicationListener<MyEvent> {public MyAppListener() {System.out.println("MyListener,监听器初始化");}@Overridepublic void onApplicationEvent(MyEvent event) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("[" + Thread.currentThread().getName() + "] MyAppListener 监听到事件 " + event);}
}// 第二种方式:@EventListener注解
@Component
public class EventHandler {@EventListener()public void eventListener(MyEvent myEvent) {System.out.println("[" + Thread.currentThread().getName() + "] eventListener 处理事件:" + myEvent);}
}

第三步:可选,自定义广播器,spring默认的广播器没有使用多线程,所以可以自定义一个广播器,使用线程池来处理事件

@Configuration
@ComponentScan("org.wyj")
public class AppConfig {@Beanpublic ExecutorService executorService() {return Executors.newFixedThreadPool(3);}// 自定义广播器@Beanpublic ApplicationEventMulticaster applicationEventMulticaster(ExecutorService executorService) {SimpleApplicationEventMulticaster eventMulticast = new SimpleApplicationEventMulticaster();eventMulticast.setTaskExecutor(executorService);return eventMulticast;}
}

测试:发布事件

public class Demo8App {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(AppConfig.class);System.out.println("-----发布事件------");applicationContext.publishEvent(new MyEvent("aaa"));System.out.println("-----发布事件结束-----");try {Thread.sleep(1000L);} catch (InterruptedException e) {throw new RuntimeException(e);}ExecutorService pool = applicationContext.getBean(ExecutorService.class);pool.shutdown();applicationContext.close();}
}

事件机制中的组件

事件机制中的组件:事件对象、广播器、事件监听器,

每个组件的创建方式:

  • 事件对象:继承ApplicationEvent的类,可以作为事件对象,存储事件中的数据
  • 广播器:这是由spring来实现的,用户不需要接触广播器,
  • 事件监听器:实现ApplicationListener接口的类,可以作为监听器,监听某种类型的事件

发布事件:用户可以直接使用spring容器来发布事件

事件对象 ApplicationEvent

ApplicationEvent:用于存储事件数据

public abstract class ApplicationEvent extends EventObject {// 记录事件发生的时间 private final long timestamp;// 参数source:存储了事件中的数据    public ApplicationEvent(Object source) {super(source);this.timestamp = System.currentTimeMillis();}
}

EventObject:ApplicationEvent的父类,它是java.util包下的类

public class EventObject implements java.io.Serializable {// 存储了事件中的数据 protected transient Object  source;
}

监听器

ApplicationListener

ApplicationListener:监听器接口

// 函数式接口,接口上的泛型必须是ApplicationEvent的子类
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {// 用于处理事件的方法 void onApplicationEvent(E event);}// ApplicationListener的父类:EventListener,一个标记接口,里面没有方法
public interface EventListener {
}

@EventListener

@EventListener:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {@AliasFor("classes")Class<?>[] value() default {};// 监听器处理什么类型的数据,也可以不指定,spring会根据方法的形参自动解析@AliasFor("value")Class<?>[] classes() default {};// spel表达式,处理事件的条件String condition() default "";}

广播器 ApplicationEventMulticaster

ApplicationEventMulticaste:

public interface ApplicationEventMulticaster {// 广播器中监听器的增删改查void addApplicationListener(ApplicationListener<?> listener);void addApplicationListenerBean(String listenerBeanName);void removeApplicationListener(ApplicationListener<?> listener);void removeApplicationListenerBean(String listenerBeanName);void removeAllListeners();// 发布事件void multicastEvent(ApplicationEvent event);void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}

事件流程

广播器的初始化

在refresh方法中初始化广播器:

protected void initApplicationEventMulticaster() {// 获取bean工厂 ConfigurableListableBeanFactory beanFactory = getBeanFactory();// APPLICATION_EVENT_MULTICASTER_BEAN_NAME: applicationEventMulticaster// 如果spring容器中包含指定名称的广播器,使用指定的广播器,用户自定义广播器就是在这个位置,// 用户定义的广播器名称需要符合spring的要求if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isTraceEnabled()) {logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else {// 如果用户没有自定义广播器,使用默认的广播器 SimpleApplicationEventMulticasterthis.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isTraceEnabled()) {logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");}}
}

注册事件监听器

在refresh方法中,实例化广播器后,随后就会向广播器中注册监听器:

protected void registerListeners() {// 首先注册手动添加的监听器,手动添加就是调用addApplicationListener方法添加的listener,// 它们此前被放入applicationListeners缓存集合// Register statically specified listeners first.for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// 将beanFactory中的所有ApplicationListener类型的bean定义对应的beanName找出来,// 把这些beanName添加到广播器中// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let post-processors apply to them!String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}// Publish early application events now that we finally have a multicaster...Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}
}

ApplicationListener的处理

ApplicationListenerDetector:处理实现了ApplicationListener接口的bean

1、这个处理器是在什么时候注册的?

// refresh方法中的第二步
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// ....// 注册后置处理器 ApplicationListenerDetector// Register early post-processor for detecting inner beans as ApplicationListeners.beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// ...
}

2、处理器中的扩展点

class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {private final transient AbstractApplicationContext applicationContext;private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);// 处理bean信息的扩展点@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {this.singletonNames.put(beanName, beanDefinition.isSingleton());  // 记录bean的作用范围}// 初始化后的扩展点@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {// 如果bean实现了ApplicationListener接口if (bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrievalBoolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {  // 这儿判断bean是不是单例// bean是单例的,把bean添加到广播器中// singleton bean (top-level or inner): register on the flythis.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}this.singletonNames.remove(beanName);}}return bean;}}

@EventListener注解的处理

@EventListener注解的处理

第一步:在spring容器启动时,会向容器中注入一个bean工厂后置处理器,用于处理@EventListener注解

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(// .... 省略代码// 注册EventListenerMethodProcessor,它是bean工厂后置处理器,// EVENT_LISTENER_PROCESSOR_BEAN_NAME:org.springframework.context.event.internalEventListenerProcessor if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}// 注册DefaultEventListenerFactory,为被@EventListener标注的方法生成适配器类// EVENT_LISTENER_FACTORY_BEAN_NAME: org.springframework.context.event.internalEventListenerFactoryif (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;
}

注册的后置处理器:

  • EventListenerMethodProcessor:bean工厂后置处理器
  • DefaultEventListenerFactory:工厂类

第二步:EventListenerMethodProcessor,用于处理@EventListener注解,它会把被@EventListener注解标注的方法封装到ApplicationListener实例中,它实现了SmartInitializingSingleton接口,会在所有的bean都被实例化完成之后执行,

1、继承自beanFactoryPostProcessor中的方法:

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {this.beanFactory = beanFactory;// 获取EventListenerFactory的实例,将它保存到成员变量中Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);List<EventListenerFactory> factories = new ArrayList<>(beans.values());AnnotationAwareOrderComparator.sort(factories);this.eventListenerFactories = factories;
}

2、继承自SmartInitializingSingleton接口中的方法,这个方法会在所有bean都实例化完成之后执行

private void processBean(final String beanName, final Class<?> targetType) {if (!this.nonAnnotatedClasses.contains(targetType) && !isSpringContainerClass(targetType)) {// 获取被@EventListener注解标注的方法Map<Method, EventListener> annotatedMethods = null;try {annotatedMethods = MethodIntrospector.selectMethods(targetType,(MethodIntrospector.MetadataLookup<EventListener>) method ->AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));}catch (Throwable ex) {// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.if (logger.isDebugEnabled()) {logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);}}if (CollectionUtils.isEmpty(annotatedMethods)) {this.nonAnnotatedClasses.add(targetType);if (logger.isTraceEnabled()) {logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());}}else {// 如果有被@EventListener注解标注的方法// Non-empty set of methodsConfigurableApplicationContext context = this.applicationContext;Assert.state(context != null, "No ApplicationContext set");List<EventListenerFactory> factories = this.eventListenerFactories;Assert.state(factories != null, "EventListenerFactory List not initialized");for (Method method : annotatedMethods.keySet()) {for (EventListenerFactory factory : factories) {if (factory.supportsMethod(method)) {Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));// 使用DefaultEventListenerFactory,把方法包装到一个ApplicationListener实例中ApplicationListener<?> applicationListener =factory.createApplicationListener(beanName, targetType, methodToUse);if (applicationListener instanceof ApplicationListenerMethodAdapter) {((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);}// 手动注册监听器context.addApplicationListener(applicationListener);break;}}}if (logger.isDebugEnabled()) {logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +beanName + "': " + annotatedMethods);}}}
}

总结:

  • 处理ApplicationListener接口的后置处理器:ApplicationListenerDetector,它是一个bean后置处理器,如果bean实现了ApplicationListener接口,会把bean注册到广播器中
  • 处理@EventListener注解的后值处理器:EventListenerMethodProcessor,它是一个bean工厂后置处理器,它同时继承了SmartInitializingSingleton,会在所有bean实例化之后执行,它会寻找被@EventListener注解标注的方法,把方法包装到一个ApplicationListener实例中,然后手动注册监听器

发布事件

发布事件的API:用户可以直接调用spring容器来发布事件

// AbstractApplicationContext类
@Override
public void publishEvent(ApplicationEvent event) {publishEvent(event, null);
}

spring容器会调用广播器来发布事件:

// SimpleApplicationEventMulticaster类
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {// 解析事件类型,以事件对象的类对象作为事件类型ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));// 根据事件对象和事件类型,获取可用的监听器。for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {Executor executor = getTaskExecutor();// 如果有线程池,在线程池中处理事件,否则在当前线程中处理事件 if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}
}

第一步:解析事件类型

// 解析事件类型的方法:参数instance是事件对象,实际上是ApplicationEvent类型的数据
public static ResolvableType forInstance(Object instance) {Assert.notNull(instance, "Instance must not be null");if (instance instanceof ResolvableTypeProvider) {ResolvableType type = ((ResolvableTypeProvider) instance).getResolvableType();if (type != null) {return type;}}// 以事件对象的类对象作为事件类型return ResolvableType.forClass(instance.getClass());
}

第二步:获取可用的监听器

// 参数listenerType是监听器的类对象,
// 参数eventType是事件的类对象
// 方法的作用是判断监听器是否可以处理事件
protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {// 如果监听器是GenericApplicationListener或SmartApplicationListener的父类,直接返回trueif (GenericApplicationListener.class.isAssignableFrom(listenerType) ||SmartApplicationListener.class.isAssignableFrom(listenerType)) {return true;}// 获取监听器上声明的事件类型,例如,在监听器的类声明上:// public class MyAppListener implements ApplicationListener<MyEvent>// 监听器实现了ApplicationListener,并且指定了泛型是MyEvent,泛型MyEvent就是监听器// 可以处理的事件类型。在java中,可以从子类的类对象上获取父类上声明的泛型,因为此时的泛型// 是一个泛型实参ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);// 如果监听器父接口上声明的泛型为null,或者泛型和事件类型相同,表示当前监听器可以处理当前事件return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));
}// 获取到的结果会被缓存起来,方便下次直接使用

第三步:调用监听器

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {// 获取错误处理器ErrorHandler errorHandler = getErrorHandler();// 如果有可用的错误处理器,就在try块中调用监听器。if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}
}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {// 调用监听器中处理事件的方法listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}
}

总结

这里介绍了监听器的基本执行过程

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com