上篇咱们讲到实现事件监听可使用实现ApplicationListener接口 Spring中ApplicationListener -【Spring底层原理】,若是有多个方法须要监听事件,那岂不是每一个方法都要放在类中实现ApplicationListener接口,这样并非很方便,因此spring为咱们提供了另一种方式实现事件监听:使用@EventListener注解java
注解源码以下,有以下做用:spring
/* * @author Stephane Nicoll * @author Sam Brannen * @since 4.2 * @see EventListenerMethodProcessor */
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String condition() default "";
}
复制代码
从注释能够看到是使用EventListenerMethodProcessor
这个处理器来解析方法上的EventListener
注解,EventListenerMethodProcessor
主要则是经过其实现的接口SmartInitializingSingleton
来进行处理的,后面会分析其源码。bootstrap
// 启动测试类
@Test
public void TestMain(){
// 建立IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// 本身发布一个事件
applicationContext.publishEvent(new ApplicationEvent("本身发布的事件") {
});
applicationContext.close();
}
// 事件触发
@Service
public class UserService {
// 当容器中发布事件后,该方法会触发
@EventListener(classes = {ApplicationEvent.class})
public void listener1(ApplicationEvent event){
System.out.println("监听到的事件1:" + event);
}
@EventListener(classes = {ApplicationEvent.class})
public void listener2(ApplicationEvent event){
System.out.println("监听到的事件2:" + event);
}
}
// 配置类
@ComponentScan("listener")
@Configuration
public class AppConfig {
}
复制代码
运行启动类,能够看到,两个事件都被触发了,使用@EventListener注解,方便让多个方法触发数组
上面讲到是使用EventListenerMethodProcessor
这个处理器来解析方法上的EventListener注解,点进EventListenerMethodProcessor
查看,发现实现了SmartInitializingSingleton
接口,主要就是经过该接口实现的。markdown
public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {}
复制代码
public interface SmartInitializingSingleton {
/** * 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
接口有个afterSingletonsInstantiated
方法,当单实例bean所有建立完成,会触发这个接口,执行afterSingletonsInstantiated
方法,相似于ContextRefreshedEvent
app
咱们在afterSingletonsInstantiated
方法上打上断点,看看源码是什么时候调用该方法执行的。ide
经过方法调用栈,容器建立对象,调用refresh()方法刷新容器——>finishBeanFactoryInitialization(beanFactory)——>preInstantiateSingletons()初始化剩下的单实例beanoop
这里便到了咱们上面分析的SmartInitializingSingleton#afterSingletonsInstantiated方法,也就是@EventListener注解注解起做用的地方源码分析
@Override
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);
// 遍历beanName,建立bean,即非懒加载单实例bean的初始化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 建立对象
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 建立完bean后判断各bean是否实现了SmartInitializingSingleton,若是是则执行 smartSingleton.afterSingletonsInstantiated()方法
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// 执行afterSingletonsInstantiated
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
复制代码