Spring3.2.6中事件驱动模型实现原理深入源码分析

Spring3.2.6中事件驱动模型实现原理深入源码分析

本次学习,是在新入公司熟悉项目时候开始的。因为是做页游的项目,所以涉及到gameServer做会将游戏中的业务操作日志交给logServer处理。在本次项目中是采用spring自带的事件驱动模型(Event-Listener)来完成的,所以就花时间深入spring和jdk源码好好分析了其实现原理,收获颇多,故在此记录,留做以后复习查看。

什么叫事件驱动模型?

要了解什么是事件驱动模型,首先要知道下面这样几个概念,我以JDK中GUI的按钮点击做说明。
  1. 事件(Event): 用户点击按钮(Button),就会产生事件(Event)。这里就是点击事件(ClickEvent)。
  2. 事件源(EventSource):发生事件的根源(场所)就是事件源。这里按钮组件就是事件源。
  3. 事件监听器(EventListener):监听特定的事件并处理的程序。这里监听器就是点击事件的处理者。
  4. 事件分发者(EventDispatcher):将发生的事件通知相对应的事件处理者的程序。这里就是通知监听器处理事件的程序。
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.WindowConstants;


/** 
 * @Description: JDK中GUI按钮的点击事件演示
 * @author Yang Gao 
 * @date 2016-3-28 上午9:48:42 
 *  
 */
public class EventListenerTest {

    public static void main(String[] args) {
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        //当前屏幕中心点的X坐标
        final int CONTENT_X = d.width/2;
        //当前屏幕中心点的Y坐标
        final int CONTENT_Y = d.height/2;

        //Windos窗口组件
        JFrame f = new JFrame("测试窗口");
        //窗口组件大小
        f.setSize(300, 200);
        //窗口组件位置
        f.setLocation((CONTENT_X - f.getWidth()/2), (CONTENT_Y - f.getHeight()/2));
        //设置大小不可改变
        f.setResizable(false);
        //设置可见性为可见
        f.setVisible(true);
        //设置默认关闭调用事件
        f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        //按钮组件,事件源
        JButton btn = new JButton("点击我哟!");
        //设置按钮组件的大小
        btn.setSize(150, 50);
        //面板添加组件
        f.add(btn);
        //对事件源添加事件监听器
        btn.addActionListener(new MyListener());
    }

}

/**
 * @Description: 自定义clickListenert类
 * @author Yang Gao 
 * @date 2016-3-28 上午10:17:16 
 *
 */
class MyListener implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {
        JButton btn = (JButton)e.getSource();
        JOptionPane.showMessageDialog(null,"我是事件监听器的处理程序,我处理的是:【" + btn.getText() + "】"); 
    }

}

在上面的code中btn.addActionListener(new MyListener());至于jdk是如何将用户产生的click事件通知给MyListener,也就是事件发布者这个角色,这里不详细叙述,有兴趣的童鞋可以考虑跟进jdk源码来找到答案。

Spring是如何实现?

Spring3.2.6中事件驱动模型实现原理深入源码分析_第1张图片
1.先看看所有事件Event类都要继承的父类EventObject(JDK)代码。

package java.util;

/**
 * 

* The root class from which all event state objects shall be derived. *

* All Events are constructed with a reference to the object, the "source", * that is logically deemed to be the object upon which the Event in question * initially occurred upon. * * @since JDK1.1 */ public class EventObject implements java.io.Serializable { private static final long serialVersionUID = 5516075349620653480L; /** * The object on which the Event initially occurred. */ protected transient Object source; /** * Constructs a prototypical Event. * * @param source The object on which the Event initially occurred. * @exception IllegalArgumentException if source is null. */ public EventObject(Object source) { if (source == null) throw new IllegalArgumentException("null source"); this.source = source; } /** * The object on which the Event initially occurred. * * @return The object on which the Event initially occurred. */ public Object getSource() { return source; } /** * Returns a String representation of this EventObject. * * @return A a String representation of this EventObject. */ public String toString() { return getClass().getName() + "[source=" + source + "]"; } }

再看看Spring中继承EventObject的类,ApplicationEvent的具体代码

/*
 * Copyright 2002-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context;

import java.util.EventObject;

/**
 * Class to be extended by all application events. Abstract as it
 * doesn't make sense for generic events to be published directly.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
public abstract class ApplicationEvent extends EventObject {

    /** use serialVersionUID from Spring 1.2 for interoperability */
    private static final long serialVersionUID = 7099057708183571937L;

    /** System time when the event happened */
    private final long timestamp;


    /**
     * Create a new ApplicationEvent.
     * @param source the component that published the event (never {@code null})
     */
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }


    /**
     * Return the system time in milliseconds when the event happened.
     */
    public final long getTimestamp() {
        return this.timestamp;
    }

}

2.接下来,我们看看所有事件监听器Listener类都要实现的EventListener(JDK)接口。

/*
 * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.util;

/**
 * A tagging interface that all event listener interfaces must extend.
 * @since JDK1.1
 */
public interface EventListener {
}

那么Spring中实现了这个接口的是接口ApplicationListener< E extends ApplicationEvent > ,很明显使用的泛型,约定了其事件类型,看看具体代码。

package org.springframework.context;

import java.util.EventListener;

/**
 * Interface to be implemented by application event listeners.
 * Based on the standard {@code java.util.EventListener} interface
 * for the Observer design pattern.
 *
 * 

As of Spring 3.0, an ApplicationListener can generically declare the event type * that it is interested in. When registered with a Spring ApplicationContext, events * will be filtered accordingly, with the listener getting invoked for matching event * objects only. * * @author Rod Johnson * @author Juergen Hoeller * @param the specific ApplicationEvent subclass to listen to * @see org.springframework.context.event.ApplicationEventMulticaster */ public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }

从上面可以看出,当泛型约定的事件发生时候,会调用其onApplicationEvent的实现方法处理。我们再看看spring中实现这一接口的子接口:SmartApplicationListener的具体代码。


package org.springframework.context.event;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;

/**
 * Extended variant of the standard {@link ApplicationListener} interface,
 * exposing further metadata such as the supported event type.
 *
 * @author Juergen Hoeller
 * @since 3.0
 */
public interface SmartApplicationListener extends ApplicationListener, Ordered {

    /**
     * Determine whether this listener actually supports the given event type.
     */
    boolean supportsEventType(Classextends ApplicationEvent> eventType);

    /**
     * Determine whether this listener actually supports the given source type.
     */
    boolean supportsSourceType(Class sourceType);

}

从上面的代码上可以看出,这个子接口添加了更为具体的类型判断,supportsEventType表示仅支持对应的事件类型,supportsSourceType表示仅支持对应的事件类型(这里就对应EventObject类中被transient瞬态修饰符的变量Object source)。

3.最后我们再看看最核心的东东,就是事件分发器(EventDispatcher)。Spring中使用接口ApplicationEventPublisher和接口ApplicationEventMulticaster来共同完成,首先我们来看一下两个接口定义的通用方法有哪些?

package org.springframework.context;
public interface ApplicationEventPublisher {
    /**
     * Notify all listeners registered with this application of an application
     * event. Events may be framework events (such as RequestHandledEvent)
     * or application-specific events.
     * @param event the event to publish
     * @see org.springframework.web.context.support.RequestHandledEvent
     */
    void publishEvent(ApplicationEvent event);
}
package org.springframework.context.event;

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

public interface ApplicationEventMulticaster {

    /**
     * Add a listener to be notified of all events.
     * @param listener the listener to add
     */
    void addApplicationListener(ApplicationListener listener);

    /**
     * Add a listener bean to be notified of all events.
     * @param listenerBeanName the name of the listener bean to add
     */
    void addApplicationListenerBean(String listenerBeanName);

    /**
     * Remove a listener from the notification list.
     * @param listener the listener to remove
     */
    void removeApplicationListener(ApplicationListener listener);

    /**
     * Remove a listener bean from the notification list.
     * @param listenerBeanName the name of the listener bean to add
     */
    void removeApplicationListenerBean(String listenerBeanName);

    /**
     * Remove all listeners registered with this multicaster.
     * 

After a remove call, the multicaster will perform no action * on event notification until new listeners are being registered. */ void removeAllListeners(); /** * Multicast the given application event to appropriate listeners. * @param event the event to multicast */ void multicastEvent(ApplicationEvent event); }

从上面可以很清楚的看出,其中ApplicationEventPublisher 接口主要负责将事件发布,ApplicationEventMulticaster 接口主要负责事件通知(回调)。Spring中ApplicationContext接口实现了ApplicationEventPublisher 接口,具体实现类是AbstractApplicationContext,让我们看看源代码中对publishEvent实现的具体代码。


    /**
     * Publish the given event to all listeners.
     * 

Note: Listeners get initialized after the MessageSource, to be able * to access it within listener implementations. Thus, MessageSource * implementations cannot publish events. * @param event the event to publish (may be application-specific or a * standard framework event) */ public void publishEvent(ApplicationEvent event) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } getApplicationEventMulticaster().multicastEvent(event); if (this.parent != null) { this.parent.publishEvent(event); } } /** * Return the internal ApplicationEventMulticaster used by the context. * @return the internal ApplicationEventMulticaster (never {@code null}) * @throws IllegalStateException if the context has not been initialized yet */ private ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException { if (this.applicationEventMulticaster == null) { throw new IllegalStateException("ApplicationEventMulticaster not initialized - " + "call 'refresh' before multicasting events via the context: " + this); } return this.applicationEventMulticaster; }

大家应该发现了,就和我画的图一样,具体实现的是接口ApplicationEventMulticaster 。那么ApplicationEventMulticaster 接口的具体实现代码是什么呢?我们接着跟进,看看实现ApplicationEventMulticaster 接口中multicastEvent方法的具体类SimpleApplicationEventMulticaster的源代码。

package org.springframework.context.event;
import java.util.concurrent.Executor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    private Executor taskExecutor;

    /**
     * Create a new SimpleApplicationEventMulticaster.
     */
    public SimpleApplicationEventMulticaster() {
    }

    /**
     * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
     */
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }


    /**
     * Set the TaskExecutor to execute application listeners with.
     * 

Default is a SyncTaskExecutor, executing the listeners synchronously * in the calling thread. *

Consider specifying an asynchronous TaskExecutor here to not block the * caller until all listeners have been executed. However, note that asynchronous * execution will not participate in the caller's thread context (class loader, * transaction association) unless the TaskExecutor explicitly supports this. * @see org.springframework.core.task.SyncTaskExecutor * @see org.springframework.core.task.SimpleAsyncTaskExecutor */ public void setTaskExecutor(Executor taskExecutor) { this.taskExecutor = taskExecutor; } /** * Return the current TaskExecutor for this multicaster. */ protected Executor getTaskExecutor() { return this.taskExecutor; } @SuppressWarnings("unchecked") public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } } }

问题的关键到了,就是这个方法getApplicationListeners(final ApplicationEvent event),从方法的定义上就不难看出,这个方法是根据事件得到其所有监听器的集合。让我们继续跟进AbstractApplicationEventMulticaster类中的getApplicationListeners这个方法查看里面的奥秘。

/**
     * Return a Collection of ApplicationListeners matching the given
     * event type. Non-matching listeners get excluded early.
     * @param event the event to be propagated. Allows for excluding
     * non-matching listeners early, based on cached matching information.
     * @return a Collection of ApplicationListeners
     * @see org.springframework.context.ApplicationListener
     */
    protected Collection getApplicationListeners(ApplicationEvent event) {
        // 事件字节码(这里我们就是zhangsanEvent和WangwuEvent两个事件)
        Class eventType = event.getClass();
        // 事件源信息的字节码(这里就是我们定义的两个事件的区别:eventName构造方法里面的source)
        Object source = event.getSource();      
        Class sourceType = (source != null ? source.getClass() : null);
        // ListenerCacheKey 保存上面的两个字节码信息
        ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
        // Map retrieverCache将匹配过的事件与监听器对应关系保存在内种中作为缓存
        ListenerRetriever retriever = this.retrieverCache.get(cacheKey);// 这里是从内存的缓存中查找
        if (retriever != null) {
            return retriever.getApplicationListeners();
        }
        else {
            // 第一次没有找到,就自己new一个ListenerRetriever来保存返回数据
            retriever = new ListenerRetriever(true);
            LinkedList allListeners = new LinkedList();
            Set listeners;
            Set listenerBeans;
            /**
            * defaultRetriever默认监听器
            * 在applicationContext容器初始化的时候就已经保存了
            * 所有实现ApplicationListener或SmartApplicationListener接口listeners
            * /
            synchronized (this.defaultRetriever) {
                listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
                listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
            }
            //遍历所有实现了ApplicationListener或SmartApplicationListener接口listeners
            for (ApplicationListener listener : listeners) {
                //supportsEvent(根据eventType和source,从listeners中筛选出符合条件的listener)
                if (supportsEvent(listener, eventType, sourceType)) {
                    retriever.applicationListeners.add(listener);
                    allListeners.add(listener);
                }
            }
            if (!listenerBeans.isEmpty()) {
                BeanFactory beanFactory = getBeanFactory();
                for (String listenerBeanName : listenerBeans) {
                    ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                        retriever.applicationListenerBeans.add(listenerBeanName);
                        allListeners.add(listener);
                    }
                }
            }
            OrderComparator.sort(allListeners);
            this.retrieverCache.put(cacheKey, retriever);
            return allListeners;
        }
    }

在上面代码中有一个狠重要的方法supportsEvent,这个方法我说过是SmartApplicationListener接口定义的。这里如果用户自定义listener是直接实现该接口,那么这里就会调用用户自己的现实类;否则就会调用spring默认的,具体我们看抽象类AbstractApplicationEventMulticaster中supportsEvent方法的源代码说话。

    /**
     * Determine whether the given listener supports the given event.
     * 

The default implementation detects the {@link SmartApplicationListener} * interface. In case of a standard {@link ApplicationListener}, a * {@link GenericApplicationListenerAdapter} will be used to introspect * the generically declared type of the target listener. * @param listener the target listener to check * @param eventType the event type to check against * @param sourceType the source type to check against * @return whether the given listener should be included in the * candidates for the given event type */ protected boolean supportsEvent( ApplicationListener listener, Class eventType, Class sourceType) { /** * 从这行代码可以看出来,如果传进来的listener实现SmartApplicationListener的类, * 那么就会调用其实现类的supportsEventType和supportsSourceType方法; * 否则就会调用GenericApplicationListenerAdapter的supportsEventType和supportsSourceType方法 * / SmartApplicationListener smartListener = (listener instanceof SmartApplicationListener ? (SmartApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }

好,我们接着跟进查看Spring自己实现SmartApplicationListener接口的类GenericApplicationListenerAdapter,它的源代码。


package org.springframework.context.event;

import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;

public class GenericApplicationListenerAdapter implements SmartApplicationListener {

    private final ApplicationListener delegate;


    public GenericApplicationListenerAdapter(ApplicationListener delegate) {
        Assert.notNull(delegate, "Delegate listener must not be null");
        this.delegate = delegate;
    }


    @SuppressWarnings("unchecked")
    public void onApplicationEvent(ApplicationEvent event) {
        this.delegate.onApplicationEvent(event);
    }
    // 这里是仅支持事件调用方法的实现
    public boolean supportsEventType(Class eventType) {
        //这里是获取listener中泛型定义的ApplicationEvent中指定delegate的字节码信息
        Class typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
        // 判断是否是ApplicationEvent类
        if (typeArg == null || typeArg.equals(ApplicationEvent.class)) {
            // 获取指定类继承的父类
            Class targetClass = AopUtils.getTargetClass(this.delegate);
            if (targetClass != this.delegate.getClass()) {
                // 这里是获取listener中泛型定义的ApplicationEvent中指定targetClass的字节码信息
                typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class);
            }
        }
        /**
        * isAssignableFrom用来判断一个类Class1和另一个类Class2是否相同
        * 或者一个类class1是另一个类class2的超类或接口
        * 注意调用顺序是class1.isAssignableFrom(class2)
        */
        // null 表示没有泛型为任意类型
        return (typeArg == null || typeArg.isAssignableFrom(eventType));
    }
    // 这里是仅支持事件源信息调用方法的实现
    public boolean supportsSourceType(Class sourceType) {
        return true;
    }

    public int getOrder() {
        return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : Ordered.LOWEST_PRECEDENCE);
    }

}

好了,到了这里大家基本也都知道这份分发器原理了,这里说的主要是通过supportsEventType和supportsSourceType这两个方法,来判断什么样的ApplicationEvent用什么样的ApplicationListener来处理了。

Spring两种事件监听方式的实现示例?

1.首先,我自定义一个我们自己的事件父类IEvent


import org.springframework.context.ApplicationEvent;

/** 
 * @Description: 自定义事件父类,根据事件名称区别
 * @author Yang Gao 
 * @date 2016-3-25 下午4:36:20 
 *  
 */
public class IEvent extends ApplicationEvent {

    private static final long serialVersionUID = -1130255953722074726L;

    private String eventName; 


    public IEvent(String eventName) {
        super(eventName);
        this.eventName = eventName;
    }

    public String getEventName() {
        return eventName;
    }


}

2.然后在再定义两个不同的事件类,ZhangsanEvent和WangwuEvent

package com.gy.event;
/** 
 * @author Yang Gao 
 * @date 2016-3-25 下午4:44:57 
 *  
 */
public class ZhangsanEvent extends IEvent { 

    private static final long serialVersionUID = 4328148476272415442L;

    public ZhangsanEvent(String source) {
        super(source);
    }
}
package com.gy.event;
/**  
 * @author Yang Gao
 * @date 2016-3-25 下午4:44:57 
 *  
 */
public class WangwuEvent extends IEvent {   

    private static final long serialVersionUID = 4328148476272415442L;

    public WangwuEvent(String source) {
        super(source);
    }
}

好了,我们来看一下具体的继承关系。

Spring3.2.6中事件驱动模型实现原理深入源码分析_第2张图片

3.然后我们在定义自己的Listenter,这里我使用Spring的两种实现方式

package com.gy.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.stereotype.Component;
import com.gy.event.ZhangsanEvent;
/** 
 * @Description: 使用实现间接实现ApplicationListener的子接口SmartApplicationListener方式
 * @author Yang Gao 
 * @date 2016-3-25 下午4:42:26 
 *  
 */
public class ZhangsanListener implements SmartApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        ZhangsanEvent _event = (ZhangsanEvent)event;
        System.out.println("ZhangsanListener Handle Event Name is " + _event.getEventName());

    }

    @Override
    public int getOrder() {
        return 0;
    }

    /* 
     * 决定监听器处理支持的事件类型
     */
    @Override
    public boolean supportsEventType(Class eventType) {
        return ZhangsanEvent.class.isAssignableFrom(eventType);
    }

    /* 
     * 决定监听器处理支持的事件源类型
     */
    @Override
    public boolean supportsSourceType(Class sourceType) {
        return Object.class.isAssignableFrom(sourceType);
    }
}
package com.gy.listener;

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

import com.gy.event.WangwuEvent;

/** 
 * @Description: 使用直接实现ApplicationListener方式,泛型指定监听的具体事件类型
 * @author Yang Gao 
 * @date 2016-3-25 下午4:43:56 
 *  
 */
public class WangwuListener implements ApplicationListener<WangwuEvent> {

    @Override
    public void onApplicationEvent(WangwuEvent event) {
        System.out.println("WangwuListener Handle Event Name is " + event.getEventName());
    }

}

4.然后咱在弄一个测试类SpringEventListenerTest

package com.gy.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

import com.gy.event.WangwuEvent;
import com.gy.event.ZhangsanEvent;

/** 
 * @Description: 测试类
 * @author Yang Gao 
 * @date 2016-3-25 下午4:35:30 
 *  
 */

public class SpringEventListenerTest {


    public static void main(String[] args) {
        ApplicationContext springContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        ZhangsanEvent zsEvent = new ZhangsanEvent("张三");
        WangwuEvent wwEvent = new WangwuEvent("王五");
        springContext.publishEvent(zsEvent);
        springContext.publishEvent(wwEvent);        

    }

}

5.最后简单的applicationContext.xml配置文件,当然至于spring3.2.6的jar包,大家都自己动手去网上下载啦,我就不粘了。


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util">


    <bean id="zhangsanListener" class="com.gy.listener.ZhangsanListener"/>
    <bean id="wangwuListener" class="com.gy.listener.WangwuListener"/>


beans>

6.好了,run一下,就结束了,让我们来看下结果。
Spring3.2.6中事件驱动模型实现原理深入源码分析_第3张图片

补充

总之,这次学习,由于时间比较充足,所以也特意花时间来写博客记录下来供以后复习用。当然,收获也是挺多的,包括在写博客回顾一遍也有收获。另外,这在提醒自己,以后有时间了要去看看Spring加载ApplicaitonContext的全过程,这样也会加深自己对Ioc和Aop的理解,也能更进一步的学习JDK的反射(Reflect)机制和事件驱动模型。


你可能感兴趣的:(Spring3.2.6)