上篇咱們講到實現事件監聽可使用實現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();
}
}
}
複製代碼