Spring4.0.4
Spring 事件机制采用的是观察者模型(又叫订阅发布模型)
有以下角色
这里,观察者就是监听者,被观察者就是事件对象。
事件发布流程如下
下面以ClassPathXmlApplicationContext初始化完后,发布,容器完成事件,为例说明
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("xxx.xml");
执行以上模板代码,启动Spring容器时,会调用
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();//在父类AbstractApplicationContext中实现
}
}
AbstractApplicationContext类方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
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.
//spring完成了容器启动。就发了一个事件通知监听者
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
以上即使Spring启动流程,也是Spring模板方法模式的体现
// Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Initialize other special beans in specific context subclasses. onRefresh();//都是在子类实现的,,题外话。接着,看finishRefresh()
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.//发送一个完成事件ContextRefreshedEvent
//ContextRefreshedEvent 继承自 ApplicationContextEvent
//ApplicationContextEvent 继承自 ApplicationEvent
//由于AbstractApplicationContext实现了ApplicationEventPublisher接口,所以它本身就是发布者
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
再看publishEvent实现
@Override
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
*/
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;//广播器了已提前初始化好,前面refresh()方法里调用initApplicationEventMulticaster()实现。
}
//具体
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
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);//记得实现ApplicationEventMulticaster
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);//没有就默认这个,Spring 自实现的,是个内部类,下面会看到它的multicastEvent(final ApplicationEvent event)方法
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);//注册,广播器是单例的。
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
//看看multicastEvent方法
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
//.....
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void multicastEvent(final ApplicationEvent event) {
//getApplicationListeners(event),获取listeners 调用listener.onApplicationEvent(event);通知
//getApplicationListeners方法在AbstractApplicationEventMulticaster类实现
for (final ApplicationListener listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {//有线程池,还能异步执行。
executor.execute(new Runnable() {
@Override
public void run() {
listener.onApplicationEvent(event);
}
});
}
else {
listener.onApplicationEvent(event);
}
}
}
}
//AbstractApplicationEventMulticaster类中的实现
* 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<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) {
Class<? extends ApplicationEvent> eventType = event.getClass();
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);//这里用到了cache
//所有的listener对象,都放在retriever里的,
if (retriever != null) {//有缓存,就直接返回。
return retriever.getApplicationListeners();
}
else {
retriever = new ListenerRetriever(true);
LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.defaultRetriever) {
//开始疑惑this.defaultRetriever.applicationListeners从哪来,其实这个是
//AbstractApplicationContext通过addApplicationListener方法手动加进来的,这是个public方法,为配置监听器提供了更大的灵活性
listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
}
for (ApplicationListener<?> listener : listeners) {
//这里要注意下,有个验证监听者和事件类型匹配操作
//具体验证法就是 监听器的接收事件类型是不是与当前类型匹配,用的是Class.isAssignableFrom这个方法。
if (supportsEvent(listener, eventType, sourceType)) {
retriever.applicationListeners.add(listener);
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
Class<?> listenerType = beanFactory.getType(listenerBeanName);
//验证
if (listenerType == null || supportsEvent(listenerType, event)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
//验证
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
retriever.applicationListenerBeans.add(listenerBeanName);
allListeners.add(listener);
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
OrderComparator.sort(allListeners);
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(eventType, this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
this.retrieverCache.put(cacheKey, retriever);
}
return allListeners;
}
}