继续看Spring的源码
AbstractApplicationContext类中registerListeners()方法用来注册监听器。
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
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!
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);
}
}
}
先拿到所有的监听器,然后加到一个集合里getApplicationEventMulticaster()。
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);这句的意思是获取到所有的实现了ApplicationListener这个接口的类并且把他们封装成一个String[]数组,之后也加入到监听器的集合里,此集合为getApplicationEventMulticaster();
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
这里
/**
* Invoke the given listener with the given event.
* @param listener the ApplicationListener to invoke
* @param event the current event to propagate
* @since 4.1
*/
@SuppressWarnings({"unchecked", "rawtypes"})
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
listener.onApplicationEvent(event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
LogFactory.getLog(getClass()).debug("Non-matching event type for listener: " + listener, ex);
}
}
}
每个监听器run一个线程调用listener.onApplicationEvent(event);方法。
实际上就是实现了ApplicationListener接口的所有实现类注册到applicationListenerBeans容器中,往spring容器中注册发布ApplicationEvent,监听器方法将会被触发。
下面我举个例子:
MyEvent
package com.mylisten;
import org.springframework.context.ApplicationEvent;
public class MyEvent extends ApplicationEvent {
public String param1;
public String param2;
public MyEvent(Object source,String param1,String param2) {
//必须调用父类构造方法
super(source);
this.param1 = param1;
this.param2 = param2;
}
public Object getSource() {
return super.getSource();
}
public String getParam1() {
return param1;
}
public void setParam1(String param1) {
this.param1 = param1;
}
public String getParam2() {
return param2;
}
public void setParam2(String param2) {
this.param2 = param2;
}
}
MyListen
package com.mylisten;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
//观察者模式去监听ApplicationEvent事件
public class MyListen implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent arg0) {
if(arg0 instanceof MyEvent) {
MyEvent event = (MyEvent)arg0;
System.out.println(this.getClass().getName() + event.getParam1());
System.out.println(this.getClass().getName() + event.getParam2());
System.out.println(this.getClass().getName() + event.getSource());
}
}
}
MyListen2
package com.mylisten;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
//观察者模式去监听ApplicationEvent事件
public class MyListen2 implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent arg0) {
if(arg0 instanceof MyEvent) {
MyEvent event = (MyEvent)arg0;
System.out.println(this.getClass().getName() + event.getParam1());
System.out.println(this.getClass().getName() + event.getParam2());
System.out.println(this.getClass().getName() + event.getSource());
}
}
}
在XML文件中添加
<bean id="myListen" class="com.mylisten.MyListen"></bean>
<bean id="myListen2" class="com.mylisten.MyListen2"></bean>
MyListenTest
package com.mylisten;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Created by wtz on 2017/9/19.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-mvc.xml","classpath:spring-mybatis.xml"})
public class MyListenTest implements ApplicationContextAware{
@Autowired
public ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Test
public void testListen(){
MyEvent myEvent = new MyEvent("source","param1","param2");
applicationContext.publishEvent(myEvent);
}
}
这里用到了观察者模式。
applicationContext.publishEvent(myEvent);我们把MyEvent广播给所有的观察者。主题subject——MyEvent,观察者observer——MyListen,Mylisten2,他们收到ApplicationEvent事件后会触发onApplicationEvent方法。
我们可以用这个来做很多扩展,因为这个监听在spring的整个生命周期都存在。
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这个方法是关于AOP的,其实AOP的实现也是自定义标签,通过URI去找对应的Handler,之后加载所有的XML,之后init之后初始化所有的解析器,根据多态去parse解析,这里是把所有的动态代理类注册进来之后做相应处理。
在spring的xml里面我们会经常会看到
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
<property name="minPoolSize" value="${c3p0.minPoolSize}"/>
<property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}"/>
<property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/>
<property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"/>
</bean>
<!-- 配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 扫描model包 使用别名 -->
<property name="typeAliasesPackage" value="com.chat.model"/>
<!-- 扫描sql配置文件:mapper需要的xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
这种ref的写法,还有@Autowired,@Resource这种,其实这些都是ioc的依赖注入,而源码中populateBean(beanName, mbd, instanceWrapper),这个方法是利用反射进行ioc依赖注入。
其中AutowiredAnnotationBeanPostProcessor是对@Autowire注解依赖注入支持。
而CommonAnnotationBeanPostProcessor是对@Resource注解依赖注入的支持。