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}