Spring源碼解析之事件派發器和監聽器


1、監聽器實現

  實現ApplicationListener接口:

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("事件"+event);
    }
}

  使用@EventListener注解

import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class MyServiceListener {

    @EventListener(classes = ApplicationEvent.class)
    public void myService(ApplicationEvent event){
        System.out.println("MyServiceListener類接收事件:"+ event);
    }
}

 

2、源碼解析前需要了解的事件發布工具類:ApplicationEventMulticaster接口

  ApplicationEventMulticaster接口的實現類可以管理大量ApplicationListener對象並向其發布事件。

    相關方法:

      void addApplicationListener(ApplicationListener<?> listener);   (添加一個偵聽器以通知所有事件。)

      void addApplicationListenerBean(String listenerBeanName);(添加一個偵聽器以通知所有事件。)

      void multicastEvent(ApplicationEvent event);(將給定的應用程序事件多播到適當的偵聽器。)

      void multicastEvent(ApplicationEvent event, ResolvableType eventType);

  該工具類注入方式:refresh(); -->  initApplicationEventMulticaster();

this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
(APPLICATION_EVENT_MULTICASTER_BEAN_NAME=“applicationEventMulticaster”)

3、實現ApplicationListener接口方式注入監聽器相關源碼解析:

  1)、向ApplicationEventMulticaster接口(AbstractApplicationEventMulticaster實現類)添加實現ApplicationListener接口的監聽器

      refresh();  (AnnotationConfigApplicationContext.java)

       registerListeners();     (AbstractApplicationContext.java)

          String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);  

          for (String listenerBeanName : listenerBeanNames){

            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

          }

  2)spring框架注入的內部類:ApplicationListenerDetector.java   (添加實現ApplicationListener接口的監聽器)

  注入位置:refresh();  ---->prepareBeanFactory(beanFactory);------->beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

  作用:創建實現ApplicationListener接口的監聽器時,需遍歷已經注入的后置處理器(beanPostProcessors),該后置處理器向applicationContext類注入該監聽類

    

     即:ApplicationListenerDetector.java:this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);

        --->AbstractApplicationContext.java:this.applicationEventMulticaster.addApplicationListener(listener);

           ---->AbstractApplicationEventMulticaster.java:this.defaultRetriever.applicationListeners.add(listener);

 3、使用@EventListener注解的注入監聽器相關源碼解析

  相關知識點:Class類中的getMethods(),該方法是獲取本類以及父類或者父接口中所有的公共方法(public修飾符修飾的)。

        Class類中的getDeclaredMethods(),該方法是獲取本類中的所有方法,包括私有的(private、protected、默認以及public)的方法。

        Class類中的getInterfaces(),能夠獲得這個對象所實現的所有接口。

        Method類中getModifiers(),返回此類或接口以整數編碼的 Java 語言修飾符。如需要知道返回的值所代表的意思,則需要用到                                                         java.lang.reflect.Modifier 這個類,這個類提供了 static 方法和常量,可以對類和成員訪問修飾符進行解碼。

        Method.getAnnotation(Class <T> annotationClass)方法如果存在這樣的注釋,則返回指定類型的元素的注釋,否則為null。

        Class1.isAssignableFrom(Class2),是用來判斷一個類Class1和另一個類Class2是否相同或者Class1類是不是Class2的父類。   

  

  關鍵類:org.springframework.context.event.internalEventListenerProcessor(實現類:org.springframework.context.event.EventListenerMethodProcessor)

  注入位置:

    this();    (AnnotationConfigApplicationContext.java)

      ----> this.reader = new AnnotatedBeanDefinitionReader(this);  (AnnotationConfigApplicationContext.java)

         ----->this(registry, getOrCreateEnvironment(registry));    (AnnotatedBeanDefinitionReader.java)

            ----->AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);   (AnnotatedBeanDefinitionReader.java)

               ----->registerAnnotationConfigProcessors(registry, null);   (AnnotationConfigUtils.java)   

                  (在給定的注冊表中注冊所有相關的注釋后處理器)

    

  EventListenerMethodProcessor作用:

    使用EventListenerMethodProcessor處理器來解析方法上的@EventListener:

    public void afterSingletonsInstantiated()
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedAction<Object>() {
						@Override
						public Object run() {
							smartSingleton.afterSingletonsInstantiated();
							return null;
						}
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}

 EventListenerMethodProcessor.java------>  smartSingleton.afterSingletonsInstantiated() :

     @Override
	public void afterSingletonsInstantiated() {
		List<EventListenerFactory> factories = getEventListenerFactories();
		String[] beanNames = this.applicationContext.getBeanNamesForType(Object.class);
		for (String beanName : beanNames) {
			if (!ScopedProxyUtils.isScopedTarget(beanName)) {
				Class<?> type = null;
				try {
					type = AutoProxyUtils.determineTargetClass(this.applicationContext.getBeanFactory(), beanName);
				}
				catch (Throwable ex) {
				}
				if (type != null) {
					try {
						processBean(factories, beanName, type);
					}
					catch (Throwable ex) {
						throw new BeanInitializationException("Failed to process @EventListener " +
								"annotation on bean with name '" + beanName + "'", ex);
					}
				}
			}
		}
	}

EventListenerMethodProcessor.java------>processBean(factories, beanName, type)。

覆寫了MetadataLookup對象的inspect(Method method)方法。

inspect(Method method)方法:AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);改操作判斷方法是否有@EventListener注解。如果存在這樣的注釋,則返回指定類型的元素的注釋,否則為null。

AnnotationConfigUtils.registerAnnotationConfigProcessors(registry, null)方法會為容器注入名為org.springframework.context.event.internalEventListenerFactory,類型為DefaultEventListenerFactory.java,該類的方法:public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method),其根據類名,類的class,方法(有@EventListener注解),來構建一個監聽器。

protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
       //.........................
      Map<Method, EventListener> annotatedMethods = null;//存放所有有@EventListener注解的方法
        annotatedMethods = MethodIntrospector.selectMethods(targetType,
						new MethodIntrospector.MetadataLookup<EventListener>() {
							@Override
							public EventListener inspect(Method method) {
								return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
							}
						});
//.......................................
// Non-empty set of methods
for (Method method : annotatedMethods.keySet()) {
   for (EventListenerFactory factory : factories) {
      if (factory.supportsMethod(method)) {
         Method methodToUse = AopUtils.selectInvocableMethod(
               method, this.applicationContext.getType(beanName));
         ApplicationListener<?> applicationListener =
               factory.createApplicationListener(beanName, targetType, methodToUse);
         if (applicationListener instanceof ApplicationListenerMethodAdapter) {
            ((ApplicationListenerMethodAdapter) applicationListener)
                  .init(this.applicationContext, this.evaluator);
         }
         this.applicationContext.addApplicationListener(applicationListener);
         break;
      }
   }
}
}    

  

MethodIntrospector.java  --------->   selectMethods()

覆寫了MethodCallback對象的doWith(Method method)方法。

在doWith方法中,T result = metadataLookup.inspect(specificMethod); 會調用上面被覆寫的inspect方法來判斷方法是否有@EventListener注解。

public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {		
final Map<Method, T> methodMap = new LinkedHashMap<Method, T>();//存放所有有@EventListener注解的方法 Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>(); handlerTypes.addAll(Arrays.asList(targetType.getInterfaces())); for (Class<?> currentHandlerType : handlerTypes) {//遍歷本類或父接口 final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) { Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); T result = metadataLookup.inspect(specificMethod); if (result != null) { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) { methodMap.put(specificMethod, result); } } } }, ReflectionUtils.USER_DECLARED_METHODS); } return methodMap; }  

void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf),循環遍歷該類的全部方法,將method當做方法參數調用dowith方法。

	public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
		// Keep backing up the inheritance hierarchy.
		Method[] methods = getDeclaredMethods(clazz);//獲取該類的全部方法
		for (Method method : methods) {
			if (mf != null && !mf.matches(method)) {
				continue;
			}
			try {
				mc.doWith(method);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
			}
		}
		if (clazz.getSuperclass() != null) {
			doWithMethods(clazz.getSuperclass(), mc, mf);
		}
		else if (clazz.isInterface()) {
			for (Class<?> superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}

 

4、發布事件相關源碼解析:

   annotationConfigApplicationContext.publishEvent(new MyApplicationEvent("yhq"));

    ----> publishEvent(event, null);  (AbstractApplicationContext.java)

      ----->getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);     (AbstractApplicationContext.java)

        ------>(SimpleApplicationEventMulticaster.java):

	@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();
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

    ------>  getApplicationListeners(event, type)   (AbstractApplicationEventMulticaster.java)//獲取全部類型匹配的listener

      ------>   Collection<ApplicationListener<?>> listeners =  retrieveApplicationListeners(eventType, sourceType, retriever); //檢查listener是否匹配。

    ------>invokeListener(listener, event);

      ------>listener.onApplicationEvent(event);

        ----->this.bridgedMethod.invoke(bean, args);

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM