001 /*
002 * ============================================================================
003 * GNU Lesser General Public License
004 * ============================================================================
005 *
006 * Beanlet - JSE Application Container.
007 * Copyright (C) 2006 Leon van Zantvoort
008 *
009 * This library is free software; you can redistribute it and/or
010 * modify it under the terms of the GNU Lesser General Public
011 * License as published by the Free Software Foundation; either
012 * version 2.1 of the License, or (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017 * Lesser General Public License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022 *
023 * Leon van Zantvoort
024 * 243 Acalanes Drive #11
025 * Sunnyvale, CA 94086
026 * USA
027 *
028 * zantvoort@users.sourceforge.net
029 * http://beanlet.org
030 */
031 package org.beanlet;
032
033 import java.lang.annotation.ElementType;
034 import java.lang.annotation.Retention;
035 import java.lang.annotation.RetentionPolicy;
036 import java.lang.annotation.Target;
037
038 /**
039 * <p>Declares a list of interceptors. The order in which the interceptors are
040 * executed is equal to the order in which they are specified by this
041 * annotation. Interceptors can be specified at both class-level and
042 * method-level. Class-level interceptors are applied to all business methods
043 * of a beanlet, except for business methods that are marked with the
044 * {@link ExcludeClassInterceptors} annotation. Logically, method-level
045 * interceptors are only applied to the method at which they are specified.</p>
046 *
047 * <p><h3>Interceptor Execution Order</h3>
048 * Class-level interceptors are placed in front of method-level interceptors.
049 * The interceptor chain does not allow the same interceptor class more than
050 * once. The classes specified by {@link #value} MUST therefore not specify
051 * duplicate classes. If the class-level and method-level interceptor
052 * declaration share classes, the duplicate class-level interceptors are
053 * discarded. This allows the method-level annotation to override the order
054 * specified at class-level. This situation is demonstrated at example (A).
055 *
056 * <p><h3>Interceptor Instance Scope</h3>
057 * New interceptor instances are created for every beanlet instance that is
058 * constructed. These instances are always associated with this particular
059 * beanlet instance.
060 * A new interceptor chain is assembled for every single interceptor-enabled
061 * method of this beanlet instance. This interceptor chain is composed of the
062 * previously created interceptor instances. The applicability of an interceptor
063 * to more than one business method of a beanlet does not affect the
064 * relationship between the interceptor instance and the beanlet instance. Only
065 * a single instance of the interceptor class is created per beanlet instance.
066 * </p>
067 *
068 * <p><h3>Examples</h3>
069 * <b>(A)</b> Example of a beanlet with duplicate interceptor
070 * ({@code InterceptorB}) declarations. The order in which these interceptors
071 * are executed for method {@code sum(int[])} is:
072 * {@code InterceptorA}, {@code InterceptorC}, {@code InterceptorB} and finally
073 * {@code InterceptorD}.
074 * The order for {@code subtract(int, int)} is: {@code InterceptorB}
075 * and {@code InterceptorA}. Class-level interceptor {@code InterceptorC} is not
076 * installed for this method, because the {@code ExcludeClassInterceptors}
077 * annotation excludes class-level interceptors.
078 *
079 * <pre>
080 * @Interceptors({InterceptorA.class, InterceptorB.class, InterceptorC.class})
081 * public class ExampleBeanlet {
082 *
083 * @Interceptors({InterceptorB.class, InterceptorD.class})
084 * @Operation
085 * public int add(int... values) {
086 * int sum = 0;
087 * for (int value : values) {
088 * sum += value;
089 * }
090 * return sum;
091 * }
092 *
093 * @ExcludeClassInterceptors
094 * @Interceptors({InterceptorB.class, InterceptorA.class})
095 * @Operation
096 * public int subtract(int arg0, int arg1) {
097 * return arg0 - arg1;
098 * }
099 * }
100 * </pre>
101 *
102 * <b>(B)</b> Interceptor instance scope example. Only two interceptor
103 * instances are created for an instance of beanlet {@code "example"}, namely
104 * an instance of {@code InterceptorA} and an instance of {@code InterceptorB}.
105 * Hence, method {@code doIt()}, {@code doThis(String)} and
106 * {@code doThat(String)} share an instance of {@code InterceptorA}.
107 * {@code InterceptorB} is shared by {@code doThis(String)} and
108 * {@code doThat(String)}.
109 *
110 * <pre>
111 * @Interceptors({InterceptorA.class})
112 * public class ExampleBeanlet {
113 *
114 * @Run
115 * public void doIt() {
116 * }
117 *
118 * @Interceptors(InterceptorB.class)
119 * @Operation
120 * public void doThis(String this) {
121 * }
122 *
123 * @Interceptors(InterceptorB.class)
124 * @Operation
125 * public void doThat(String that) {
126 * }
127 * }
128 * </pre>
129 * </p>
130 *
131 * <p><h3>XML Representation</h3>The following xml-fragment shows how to express this annotation in xml.<br><pre><tt><beanlets xmlns="http://beanlet.org/schema/beanlet"
132 * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
133 * xsi:schemaLocation="http://beanlet.org/schema/beanlet http://beanlet.org/schema/beanlet/beanlet_1_0.xsd">
134 * <beanlet name="foo" type="com.acme.Foo">
135 * <b><interceptors type="com.acme.InterceptorA"/></b>
136 * </beanlet>
137 *</beanlets></tt></pre></p>
138 * Or alternatively:
139 * <p><pre><tt><beanlets xmlns="http://beanlet.org/schema/beanlet"
140 * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
141 * xsi:schemaLocation="http://beanlet.org/schema/beanlet http://beanlet.org/schema/beanlet/beanlet_1_0.xsd">
142 * <beanlet name="foo" type="com.acme.Foo">
143 * <b><interceptors>
144 * <class type="com.acme.InterceptorA"/>
145 * <class type="com.acme.InterceptorB"/>
146 * </interceptors></b>
147 * </beanlet>
148 *</beanlets></tt></pre></p>
149 * @author Leon van Zantvoort
150 * @see AroundInvoke
151 * @see Interceptor
152 * @see ExcludeClassInterceptors
153 */
154 @Retention(RetentionPolicy.RUNTIME)
155 @Target({ElementType.TYPE, ElementType.METHOD})
156 public @interface Interceptors {
157
158 /**
159 * Specifies interceptor classes. These classes are executed in the order
160 * they are specified.
161 */
162 Class<?>[] value();
163 }