KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > aop > aspectj > annotation > InstantiationModelAwarePointcutAdvisorImpl


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.aop.aspectj.annotation;
18
19 import java.lang.reflect.Method JavaDoc;
20
21 import org.aopalliance.aop.Advice;
22 import org.aspectj.lang.reflect.PerClauseKind;
23
24 import org.springframework.aop.Pointcut;
25 import org.springframework.aop.aspectj.AspectJExpressionPointcut;
26 import org.springframework.aop.aspectj.AspectJPrecedenceInformation;
27 import org.springframework.aop.aspectj.InstantiationModelAwarePointcutAdvisor;
28 import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.AspectJAnnotation;
29 import org.springframework.aop.support.DynamicMethodMatcherPointcut;
30 import org.springframework.aop.support.Pointcuts;
31
32 /**
33  * Internal implementation of AspectJPointcutAdvisor.
34  * Note that there will be one instance of this advisor for each target method.
35  *
36  * @author Rod Johnson
37  * @author Juergen Hoeller
38  * @since 2.0
39  */

40 class InstantiationModelAwarePointcutAdvisorImpl
41         implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation {
42
43     private final AspectJExpressionPointcut declaredPointcut;
44     
45     private Pointcut pointcut;
46     
47     private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
48     
49     private final Method JavaDoc method;
50     
51     private final boolean lazy;
52     
53     private final AspectJAdvisorFactory atAspectJAdvisorFactory;
54     
55     private Advice instantiatedAdvice;
56
57     private int declarationOrder;
58     
59     private String JavaDoc aspectName;
60     
61     private Boolean JavaDoc isBeforeAdvice = null;
62
63     private Boolean JavaDoc isAfterAdvice = null;
64
65
66     public InstantiationModelAwarePointcutAdvisorImpl(
67             AspectJAdvisorFactory af,
68             AspectJExpressionPointcut ajexp,
69             MetadataAwareAspectInstanceFactory aif,
70             Method JavaDoc method,
71             int declarationOrderInAspect,
72             String JavaDoc aspectName) {
73
74         this.declaredPointcut = ajexp;
75         this.method = method;
76         this.atAspectJAdvisorFactory = af;
77         this.aspectInstanceFactory = aif;
78         this.declarationOrder = declarationOrderInAspect;
79         this.aspectName = aspectName;
80         
81         if (aif.getAspectMetadata().isLazilyInstantiated()) {
82             // Static part of the pointcut is a lazy type.
83
Pointcut preInstantiationPointcut =
84                     Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
85             
86             // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
87
// If it's not a dynamic pointcut, it may be optimized out
88
// by the Spring AOP infrastructure after the first evaluation.
89
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
90             this.lazy = true;
91         }
92         else {
93             // A singleton aspect.
94
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
95             this.pointcut = declaredPointcut;
96             this.lazy = false;
97         }
98     }
99
100
101     /**
102      * The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
103      * depending on the state of the advice.
104      */

105     public Pointcut getPointcut() {
106         return this.pointcut;
107     }
108
109     /**
110      * This is only of interest for Spring AOP: AspectJ instantiation semantics
111      * are much richer. In AspectJ terminology, all a return of <code>true</code>
112      * means here is that the aspect is not a SINGLETON.
113      */

114     public boolean isPerInstance() {
115         return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON);
116     }
117     
118     /**
119      * Return the AspectJ AspectMetadata for this advisor.
120      */

121     public AspectMetadata getAspectMetadata() {
122         return this.aspectInstanceFactory.getAspectMetadata();
123     }
124
125     /**
126      * Lazily instantiate advice if necessary.
127      */

128     public synchronized Advice getAdvice() {
129         if (this.instantiatedAdvice == null) {
130             this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
131         }
132         return this.instantiatedAdvice;
133     }
134     
135     public boolean isLazy() {
136         return this.lazy;
137     }
138
139     public synchronized boolean isAdviceInstantiated() {
140         return (this.instantiatedAdvice != null);
141     }
142
143
144     private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
145         return this.atAspectJAdvisorFactory.getAdvice(
146                 this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
147     }
148     
149     public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
150         return this.aspectInstanceFactory;
151     }
152
153     public AspectJExpressionPointcut getDeclaredPointcut() {
154         return this.declaredPointcut;
155     }
156
157     public int getOrder() {
158         return this.aspectInstanceFactory.getOrder();
159     }
160
161     public String JavaDoc getAspectName() {
162         return this.aspectName;
163     }
164
165     public int getDeclarationOrder() {
166         return this.declarationOrder;
167     }
168
169     public boolean isBeforeAdvice() {
170         if (this.isBeforeAdvice == null) {
171             determineAdviceType();
172         }
173         return this.isBeforeAdvice;
174     }
175
176     public boolean isAfterAdvice() {
177         if (this.isAfterAdvice == null) {
178             determineAdviceType();
179         }
180         return this.isAfterAdvice;
181     }
182
183     /**
184      * Duplicates some logic from getAdvice, but importantly does not force
185      * creation of the advice.
186      */

187     private void determineAdviceType() {
188         AspectJAnnotation<?> aspectJAnnotation =
189                 AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
190         if (aspectJAnnotation == null) {
191             this.isBeforeAdvice = false;
192             this.isAfterAdvice = false;
193         }
194         else {
195             switch (aspectJAnnotation.getAnnotationType()) {
196                 case AtAfter:
197                 case AtAfterReturning:
198                 case AtAfterThrowing:
199                     this.isAfterAdvice = true;
200                     this.isBeforeAdvice = false;
201                     break;
202                 case AtAround:
203                 case AtPointcut:
204                     this.isAfterAdvice = false;
205                     this.isBeforeAdvice = false;
206                     break;
207                 case AtBefore:
208                     this.isAfterAdvice = false;
209                     this.isBeforeAdvice = true;
210             }
211         }
212     }
213
214
215     @Override JavaDoc
216     public String JavaDoc toString() {
217         return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
218             "]; advice method [" + this.method + "]; perClauseKind=" +
219             this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
220
221     }
222
223
224     /**
225      * Pointcut implementation that changes its behaviour when the advice is instantiated.
226      * Note that this is a <i>dynamic</i> pointcut. Otherwise it might
227      * be optimized out if it does not at first match statically.
228      */

229     private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
230
231         private final AspectJExpressionPointcut declaredPointcut;
232
233         private final Pointcut preInstantiationPointcut;
234
235         private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
236
237         private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
238                 Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
239             this.declaredPointcut = declaredPointcut;
240             this.preInstantiationPointcut = preInstantiationPointcut;
241             if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
242                 this.aspectInstanceFactory = (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory;
243             }
244         }
245
246         @Override JavaDoc
247         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass) {
248             // We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
249
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
250                     this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
251         }
252
253         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass, Object JavaDoc[] args) {
254             // This can match only on declared pointcut.
255
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
256         }
257
258         private boolean isAspectMaterialized() {
259             return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized());
260         }
261     }
262
263 }
264
Popular Tags