前面通过实现ApplicationListener,就可以创建一个监听了,但是还是相对麻烦,因为一般我们是把监听和业务处理分开,能不能直接把监听器注解到业务方法中?EventListener就实现了这种方法。
业务类的方法上直接添加相关的注解即可。
public class OrgServiceImpl {
@EventListener
public void add(OrgChangeEvent event){
System.out.println("org event listener "+event.getSource().toString());
}
}
上述通过: @EventListener,就创建了一个监听OrgChangeEvent的监听器。
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {
/**
* Alias for {@link #classes}.
*/
@AliasFor("classes")
Class>[] value() default {};
/**
* The event classes that this listener handles.
* If this attribute is specified with a single value, the
* annotated method may optionally accept a single parameter.
* However, if this attribute is specified with multiple values,
* the annotated method must not declare any parameters.
*/
@AliasFor("value")
Class>[] classes() default {};
String condition() default "";
}
可以针对多个事件进行注解,例如:@EventListener
({OrgChangeEvent.class, UserChangeEvent.class})
常见的方式,普通创建一个监听,需要实现ApplicationListener接口,那么EventListener注解又如何实现的?
Processing of @EventListener annotations is performed via the internal EventListenerMethodProcessor bean which gets registered automatically when using Java config or manually via the or element when using XML config.
上述EventLIstener注解的说明,发现了EventListenerMethodProcessor来实现EventListener的执行的。
EventListenerMethodProcessor实现了三个接口:SmartInitializingSingleton(Bean对象初始化完成的后置对象), ApplicationContextAware(获取ApplicationContext), BeanFactoryPostProcessor(BeanFactory的后置处理器)。按照执行顺序,ApplicationContextAware>BeanFactoryPostProcessor>SmartInitializingSignleton。其中ApplicationContextAware都熟悉,可以直接忽略。
获取eventListenerFactories对象,整个Spring默认的实现对象就一个:DefaultEventListenerFactory
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
Map beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
EventListenerFactory主要是创建ApplicationListener,看看DefaultEventListenerFactory的源码
public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {
private int order = LOWEST_PRECEDENCE;
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
@Override
public boolean supportsMethod(Method method) {
return true;
}
@Override
public ApplicationListener> createApplicationListener(String beanName, Class> type, Method method) {
//核心:创建ApplicationListener,ApplicationListenerMethodAdapter适配器
return new ApplicationListenerMethodAdapter(beanName, type, method);
}
}
SmartInitializingSignLeton的调用时机:AbstractApplicationContext.refresh(finishBeanFactoryInitialization->preInstantiateSingletons),初始化所有的非延迟加载的单例对象后,针对所有初始化完成的Bean,如果该Bean是SmartInitializingSingleton实现类,会单独调用afterSingletonsInstantiated方法。
@Override
public void afterSingletonsInstantiated() {
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
//获取所有的Bean
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class> type = null;
try {
type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (type != null) {
if (ScopedObject.class.isAssignableFrom(type)) {
try {
Class> targetClass = AutoProxyUtils.determineTargetClass(
beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != null) {
type = targetClass;
}
}
catch (Throwable ex) {
// An invalid scoped proxy arrangement - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
}
}
}
try {
//核心,处理Bean
processBean(beanName, type);
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
获取到符合条件的Bean对象,开始处理。
private void processBean(final String beanName, final Class> targetType) {
//
if (!this.nonAnnotatedClasses.contains(targetType) &&
//判断当前类是否具有EventListener注解,无论是方法还是字段,EventListener只支持方法和注解。
AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
!isSpringContainerClass(targetType)) {
Map annotatedMethods = null;
try {
//获取所有带有EventListener的方法
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
else {
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
List factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
//EventListenerFactory的钩子方法
if (factory.supportsMethod(method)) {
//获取方法,如果当前类没有,就获取接口的方法
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
//根据Bean的名称和对应的Method,调用工厂,创建监听对象,其实就是适配器监听
ApplicationListener> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
//注册监听
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
EventListener最终转化为ApplicationListenerMethodAdapter,ApplicationListenerMethodAdapter的结构如下:
因此,我们只需要看看ApplicationListenerMethodAdapter的onApplicationEvent如何处理事件的。
public void onApplicationEvent(ApplicationEvent event) {
processEvent(event);
}
public void processEvent(ApplicationEvent event) {
//组装方法执行时的参数
Object[] args = resolveArguments(event);
if (shouldHandle(event, args)) {
//执行方法
Object result = doInvoke(args);
if (result != null) {
//有意思的地方,如果返回值非null,并且是普通数据,
//例如:基本数据格式,竟然还会包装成PayloadApplicationEvent,再次发送一次事件
handleResult(result);
}
else {
logger.trace("No result object given - no result to handle");
}
}
}
@Nullable
protected Object doInvoke(Object... args) {
Object bean = getTargetBean();
// Detect package-protected NullBean instance through equals(null) check
if (bean.equals(null)) {
return null;
}
ReflectionUtils.makeAccessible(this.method);
try {
//反射相关可以忽略
return this.method.invoke(bean, args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(this.method, bean, args);
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
}
catch (InvocationTargetException ex) {
// Throw underlying exception
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else {
String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args);
throw new UndeclaredThrowableException(targetException, msg);
}
}
}
通过EventLitener的实现方式,其实后续也可以实现方法级别的注解,具体操作步骤如下:
通过SmartInitializingSignLeton的afterSingletonsInstantiated方法,获取所有Bean中带有指定注解的方法。
针对对象的特定方法生成相关的适配器对象,这样就可以正常的调用该对象的方法。
通过持有对象+方法,生成适配器对象。
其实相关的实践有很多,可以在SpringBoot中,搜索:SmartInitializingSignLeton的实现类,会发现很多能力都是通过上述方式实现。