001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.context.event; 018 019import java.lang.annotation.Documented; 020import java.lang.annotation.ElementType; 021import java.lang.annotation.Retention; 022import java.lang.annotation.RetentionPolicy; 023import java.lang.annotation.Target; 024 025import org.springframework.context.ApplicationEvent; 026import org.springframework.core.annotation.AliasFor; 027 028/** 029 * Annotation that marks a method as a listener for application events. 030 * 031 * <p>If an annotated method supports a single event type, the method may 032 * declare a single parameter that reflects the event type to listen to. 033 * If an annotated method supports multiple event types, this annotation 034 * may refer to one or more supported event types using the {@code classes} 035 * attribute. See the {@link #classes} javadoc for further details. 036 * 037 * <p>Events can be {@link ApplicationEvent} instances as well as arbitrary 038 * objects. 039 * 040 * <p>Processing of {@code @EventListener} annotations is performed via 041 * the internal {@link EventListenerMethodProcessor} bean which gets 042 * registered automatically when using Java config or manually via the 043 * {@code <context:annotation-config/>} or {@code <context:component-scan/>} 044 * element when using XML config. 045 * 046 * <p>Annotated methods may have a non-{@code void} return type. When they 047 * do, the result of the method invocation is sent as a new event. If the 048 * return type is either an array or a collection, each element is sent 049 * as a new individual event. 050 * 051 * <p>This annotation may be used as a <em>meta-annotation</em> to create custom 052 * <em>composed annotations</em>. 053 * 054 * <h3>Exception Handling</h3> 055 * <p>While it is possible for an event listener to declare that it 056 * throws arbitrary exception types, any checked exceptions thrown 057 * from an event listener will be wrapped in an 058 * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException} 059 * since the event publisher can only handle runtime exceptions. 060 * 061 * <h3>Asynchronous Listeners</h3> 062 * <p>If you want a particular listener to process events asynchronously, you 063 * can use Spring's {@link org.springframework.scheduling.annotation.Async @Async} 064 * support, but be aware of the following limitations when using asynchronous events. 065 * 066 * <ul> 067 * <li>If an asynchronous event listener throws an exception, it is not propagated 068 * to the caller. See {@link org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler 069 * AsyncUncaughtExceptionHandler} for more details.</li> 070 * <li>Asynchronous event listener methods cannot publish a subsequent event by returning a 071 * value. If you need to publish another event as the result of the processing, inject an 072 * {@link org.springframework.context.ApplicationEventPublisher ApplicationEventPublisher} 073 * to publish the event manually.</li> 074 * </ul> 075 * 076 * <h3>Ordering Listeners</h3> 077 * <p>It is also possible to define the order in which listeners for a 078 * certain event are to be invoked. To do so, add Spring's common 079 * {@link org.springframework.core.annotation.Order @Order} annotation 080 * alongside this event listener annotation. 081 * 082 * @author Stephane Nicoll 083 * @author Sam Brannen 084 * @since 4.2 085 * @see EventListenerMethodProcessor 086 */ 087@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) 088@Retention(RetentionPolicy.RUNTIME) 089@Documented 090public @interface EventListener { 091 092 /** 093 * Alias for {@link #classes}. 094 */ 095 @AliasFor("classes") 096 Class<?>[] value() default {}; 097 098 /** 099 * The event classes that this listener handles. 100 * <p>If this attribute is specified with a single value, the 101 * annotated method may optionally accept a single parameter. 102 * However, if this attribute is specified with multiple values, 103 * the annotated method must <em>not</em> declare any parameters. 104 */ 105 @AliasFor("value") 106 Class<?>[] classes() default {}; 107 108 /** 109 * Spring Expression Language (SpEL) expression used for making the event 110 * handling conditional. 111 * <p>The event will be handled if the expression evaluates to boolean 112 * {@code true} or one of the following strings: {@code "true"}, {@code "on"}, 113 * {@code "yes"}, or {@code "1"}. 114 * <p>The default expression is {@code ""}, meaning the event is always handled. 115 * <p>The SpEL expression will be evaluated against a dedicated context that 116 * provides the following metadata: 117 * <ul> 118 * <li>{@code #root.event} or {@code event} for references to the 119 * {@link ApplicationEvent}</li> 120 * <li>{@code #root.args} or {@code args} for references to the method 121 * arguments array</li> 122 * <li>Method arguments can be accessed by index. For example, the first 123 * argument can be accessed via {@code #root.args[0]}, {@code args[0]}, 124 * {@code #a0}, or {@code #p0}.</li> 125 * <li>Method arguments can be accessed by name (with a preceding hash tag) 126 * if parameter names are available in the compiled byte code.</li> 127 * </ul> 128 */ 129 String condition() default ""; 130 131}