【spring源码】十二、监听器

spring监听器

一、ApplicationListener接口

作用:监听容器中发布的事件,完成事件驱动开发

实现ApplicationListener接口

//如果要写实现类就得实现这个接口
public interface ApplicationListener<E extends ApplicationEvent> //泛型是要监听的事件,监听ApplicationEvent及其下面的子事件。即我们要发布事件,这个事件应该是ApplicationEvent的子类
    extends EventListener {
    
    //处理一个事件

    //事件到达以后,出触发该方法
    void onApplicationEvent(E event);
}

1 自定义实现

@Component //把监听器加入到容器中
public class MyApplicationListener //写一个监听器来监听某个事件(ApplicationEvent及其子类)
    implements ApplicationListener<ApplicationEvent> {
    
    

	//当容器中发布此事件以后,方法触发//默认的话我们会收到ContextRefreshedEvent和ContextClosedEvent两个事件,即容器刷新完和关闭的事件。而还有两个事件是cotextStartedEvent和ContextStopedEvent事件没有使用
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
    
    
		// TODO Auto-generated method stub
		System.out.println("收到事件:"+event);//分为开启、关闭
	}
}


// 也可以@EventListener
@Service
public class UserService {
    
    
	
	@EventListener(classes={
    
    ApplicationEvent.class})//原理:使用EventListenerMethodProcessor处理器解析方法上的@EventListener // 可以看EventListenerMethodProcessor
	public void listen(ApplicationEvent event){
    
    
		System.out.println("UserService。。监听到的事件:"+event);
	}

}

2 自己发布事件

applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件"))

public class IOCTest_Ext {
    
    
	@Test
	public void test01(){
    
    
		AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);
		
		//自己发布事件;//这里我们发布了一个容器时间
		applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")) {
    
    
		});
		
		applicationContext.close();
	}
}
//我们这里发布publish了事件,在MyApplicationListener就会监听到,并传入到event参数,此时就打印出了2+1=3个事件

二、事件监听器流程

原理:
 *  	ContextRefreshedEvent、IOCTest_Ext$1[source=我发布的时间]、ContextClosedEvent;
 *  1)、ContextRefreshedEvent事件:
 *  	1)、容器创建对象:refresh()*  	2)、⑫finishRefresh();容器刷新完成会发布ContextRefreshedEvent事件
 *  2)、自己发布事件;
 *  3)、容器关闭会发布ContextClosedEvent;
 *  
 *  【事件发布流程】:
 *  	3)、publishEvent(new ContextRefreshedEvent(this));
 *  			1)、获取事件的多播器(派发器):getApplicationEventMulticaster()
 *  			2)、multicastEvent派发事件:
 *  			3)、获取到所有的ApplicationListener;
 *  				for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    
    
 *  				1)、如果有Executor,可以支持使用Executor进行异步派发;
 *  					Executor executor = getTaskExecutor();
 *  				2)、否则,同步的方式直接执行listener方法;invokeListener(listener, event);
 *  				 拿到listener回调onApplicationEvent方法;

三、refresh中发布事件的阶段

技巧:在onApplicationEvent方法上加断点后,debug

首先收到ContextRefreshEvent事件,执行的时机是refresh方法的最后一个方法

// 实例化剩余的单例bean
finishBeanFactoryInitialization();

// refresh的最后一步:发布事件 //在他之前有initApplicationEventMulticaster();
finishRefresh();

(1)finishRefresh()

protected void finishRefresh() {
    
    
    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    //发布事件,new了一个事件  容器刷新完成
    publishEvent(new ContextRefreshedEvent(this));//容器刷新完成,发布了一个事件

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}
(2)publishEvent
  • 获取多播器
  • 多播器
public void publishEvent(ApplicationEvent event) {
    
    
    publishEvent(event, null);
}//重载
protected void publishEvent(Object event, ResolvableType eventType) {
    
    
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
    
     logger.trace("Publishing event in " + getDisplayName() + ": " + event); }

    // Decorate event as an ApplicationEvent if necessary
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
    
    
        applicationEvent = (ApplicationEvent) event;
    }
    else {
    
    
        applicationEvent = new PayloadApplicationEvent<Object>(this, event);
        if (eventType == null) {
    
    
            eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
        }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
    
    
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
    
    
        // ***获取到应用事件的派发器(多播器),即把这个事件发送给多个监听器让他们感知//然后调用multicastEvent方法 派发事件	
        getApplicationEventMulticaster().//(1) 获取多播器
            multicastEvent(applicationEvent, eventType);//(2) 派发事件
    }

    // Publish event via parent context as well...
    if (this.parent != null) {
    
    
        if (this.parent instanceof AbstractApplicationContext) {
    
    
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        }
        else {
    
    
            this.parent.publishEvent(event);
        }
    }
}
(3)multicastEvent
  • 找到监听器getApplicationListeners(event, type)
  • 给监听器发送事件invokeListener(listener, event);
public class SimpleApplicationEventMulticaster
    extends AbstractApplicationEventMulticaster {
    
    

    @Nullable
    private Executor taskExecutor;
    @Nullable
    private ErrorHandler errorHandler;
    
    @Override//派发事件
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    
    
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        // 遍历容器监听器
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    
    
            Executor executor = getTaskExecutor();//如果有executor,可以利用executor进行异步执行的话
            // 可以用多线程方式异步派发事件
            if (executor != null) {
    
    
                // 类似于线程池
                executor.execute(new Runnable() {
    
    
                    @Override
                    public void run() {
    
    
                        invokeListener(listener, event);//也是执行方法
                    }
                });
            }
            else {
    
    //同步 方式直接执行方法
                invokeListener(listener, event);
            }
        }
    }

    
(4)getApplicationListeners()
public abstract class AbstractApplicationEventMulticaster
    implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
    
    

    private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);

    final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
    @Nullable
    private ClassLoader beanClassLoader;
    @Nullable
    private ConfigurableBeanFactory beanFactory;
    private Object retrievalMutex = this.defaultRetriever;

    protected Collection<ApplicationListener<?>> getApplicationListeners(
        ApplicationEvent event, ResolvableType eventType) {
    
    

        Object source = event.getSource();
        Class<?> sourceType = (source != null ? source.getClass() : null);
        ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

        // Quick check for existing entry on ConcurrentHashMap...
        ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
        if (retriever != null) {
    
    
            return retriever.getApplicationListeners();
        }

        if (this.beanClassLoader == null ||
            (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
             (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
    
    
            // Fully synchronized building and caching of a ListenerRetriever
            synchronized (this.retrievalMutex) {
    
    
                retriever = this.retrieverCache.get(cacheKey);
                if (retriever != null) {
    
    
                    return retriever.getApplicationListeners();
                }
                retriever = new ListenerRetriever(true);
                Collection<ApplicationListener<?>> listeners =
                    retrieveApplicationListeners(eventType, sourceType, retriever);
                this.retrieverCache.put(cacheKey, retriever);
                return listeners;
            }
        }
        else {
    
    
            // No ListenerRetriever caching -> no synchronization necessary
            return retrieveApplicationListeners(eventType, sourceType, null);
        }
    }
(5)invokeListener
// SimpleApplicationEventMulticaster;
protected void invokeListener(ApplicationListener<?> listener,//监听器 
                              ApplicationEvent event) {
    
    //事件
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
    
    
        try {
    
    
            // 执行逻辑
            doInvokeListener(listener, event);//
        }
        catch (Throwable err) {
    
    
            errorHandler.handleError(err);
        }
    }
    else {
    
    
        // 执行
        doInvokeListener(listener, event);//
    }
}
doInvokeListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    
    
    try {
    
    
        // 拿到容器对象后回调 //如果我们自定义的逻辑,重写的就是onApplicationEvent方法,获得ac.close()里也有
        listener.onApplicationEvent(event);//回调
    }
    catch (ClassCastException ex) {
    
    
        String msg = ex.getMessage();
        if (msg == null || msg.startsWith(event.getClass().getName())) {
    
    
            // Possibly a lambda-defined listener which we could not resolve the generic event type for
            Log logger = LogFactory.getLog(getClass());
        }
        else {
    
    
            throw ex;
        }
    }
}

四、initApplicationEventMulticaster

public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext {
    
    
    
    public void refresh() throws BeansException, IllegalStateException {
    
    
        synchronized (this.startupShutdownMonitor) {
    
    
            ...;
            try {
    
    
                ,,,;
                invokeBeanFactoryPostProcessors(beanFactory);
                registerBeanPostProcessors(beanFactory);
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();// 初始化事件多播器

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();//注册监听器

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }
public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext {
    
    
    
    protected void initApplicationEventMulticaster() {
    
    
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 先去容器中找
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    
    //"applicationEventMulticaster";
            this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isTraceEnabled()) {
    
    
                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
    
    
            // 如果没有多播器就new一个
            this.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() + "]");
            }
        }
    }

五、registerListeners();

public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext {
    
    
    
    protected void registerListeners() {
    
    
        // Register statically specified listeners first.注册静态特殊的监听器
        for (ApplicationListener<?> listener : getApplicationListeners()) {
    
    
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        // 从容器汇总拿到所有ApplicationListener类型的bean
        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 (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
    
    
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    
    
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

六、注册监听方式

// 也可以@EventListener
@Service
public class UserService {
    
    
	
	@EventListener(classes={
    
    ApplicationEvent.class})//原理:使用EventListenerMethodProcessor处理器解析方法上的@EventListener // 可以看EventListenerMethodProcessor
	public void listen(ApplicationEvent event){
    
    
		System.out.println("UserService。。监听到的事件:"+event);
	}

}
/*
* @see EventListenerMethodProcessor
*/
@Target({
    
    ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {
    
    
EventListenerMethodProcessor
public class EventListenerMethodProcessor
    implements SmartInitializingSingleton, //
                ApplicationContextAware, 
                BeanFactoryPostProcessor {
    
    
public interface SmartInitializingSingleton {
    
    

	/**
	所有单实例bean已经创建完成
	 * Invoked right at the end of the singleton pre-instantiation phase,
	 * with a guarantee that all regular singleton beans have been created
	 * already. {@link ListableBeanFactory#getBeansOfType} calls within
	 * this method won't trigger accidental side effects during bootstrap.
	 * <p><b>NOTE:</b> This callback won't be triggered for singleton beans
	 * lazily initialized on demand after {@link BeanFactory} bootstrap,
	 * and not for any other bean scope either. Carefully use it for beans
	 * with the intended bootstrap semantics only.
	 */
	void afterSingletonsInstantiated();

}
SmartInitializingSingleton原理:
    refresh
    在finish实例化单实例bean
    
public void preInstantiateSingletons() throws BeansException {
    
    
    if (logger.isTraceEnabled()) {
    
    
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // 实例化单实例eban
    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
    
    
        ...;
        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
        ...;
    }

    // 实例化完了,
    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
    
    
        // 拿到实例化完的bean
        Object singletonInstance = getSingleton(beanName);
        // 判断是否是SmartInitializingSingleton,
        if (singletonInstance instanceof SmartInitializingSingleton) {
    
    
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
    
    
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    
    
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
    
    
                smartSingleton.afterSingletonsInstantiated();// 这里
            }
        }
    }
}
public class EventListenerMethodProcessor
    implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {
    
    
    
    @Override
    public void afterSingletonsInstantiated() {
    
    
        ConfigurableListableBeanFactory beanFactory = this.beanFactory;
        Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
        String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
        for (String beanName : beanNames) {
    
    
            if (!ScopedProxyUtils.isScopedTarget(beanName)) {
    
    
                Class<?> type = null;
                try {
    
    
                    type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
                }
                catch (Throwable ex) {
    
    
                    // An unresolvable bean type, probably from a lazy bean - let's ignore it.
                    if (logger.isDebugEnabled()) {
    
    
                        logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
                    }
                }
                if (type != null) {
    
    
                    if (ScopedObject.class.isAssignableFrom(type)) {
    
    
                        try {
    
    
                            Class<?> targetClass = AutoProxyUtils.determineTargetClass(
                                beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
                            if (targetClass != null) {
    
    
                                type = targetClass;
                            }
                        }
                        catch (Throwable ex) {
    
    
                            // An invalid scoped proxy arrangement - let's ignore it.
                            if (logger.isDebugEnabled()) {
    
    
                                logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
                            }
                        }
                    }
                    try {
    
    
                        processBean(beanName, type);
                    }
                    catch (Throwable ex) {
    
    
                        throw new BeanInitializationException("Failed to process @EventListener " +
                                                              "annotation on bean with name '" + beanName + "'", ex);
                    }
                }
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/hancoder/article/details/111413371