|
|
|
@ -16,25 +16,24 @@
|
|
|
|
|
|
|
|
|
|
package com.fr.third.springframework.aop.aspectj; |
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
|
|
|
|
|
import org.aopalliance.aop.Advice; |
|
|
|
|
import com.fr.third.aspectj.lang.reflect.PerClauseKind; |
|
|
|
|
|
|
|
|
|
import com.fr.third.springframework.aop.Pointcut; |
|
|
|
|
import com.fr.third.springframework.aop.support.DynamicMethodMatcherPointcut; |
|
|
|
|
import com.fr.third.springframework.aop.support.Pointcuts; |
|
|
|
|
import org.aopalliance.aop.Advice; |
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Internal implementation of AspectJPointcutAdvisor. |
|
|
|
|
* Note that there will be one instance of this advisor for each target method. |
|
|
|
|
* Internal implementation of AspectJPointcutAdvisor. Note that there will be one instance of this |
|
|
|
|
* advisor for each target method. |
|
|
|
|
* |
|
|
|
|
* @author Rod Johnson |
|
|
|
|
* @author Juergen Hoeller |
|
|
|
|
* @since 2.0 |
|
|
|
|
*/ |
|
|
|
|
class InstantiationModelAwarePointcutAdvisorImpl |
|
|
|
|
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { |
|
|
|
|
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { |
|
|
|
|
|
|
|
|
|
private final AspectJExpressionPointcut declaredPointcut; |
|
|
|
|
|
|
|
|
@ -58,9 +57,13 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
|
|
|
|
|
private Boolean isAfterAdvice; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp, |
|
|
|
|
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { |
|
|
|
|
public InstantiationModelAwarePointcutAdvisorImpl( |
|
|
|
|
AspectJAdvisorFactory af, |
|
|
|
|
AspectJExpressionPointcut ajexp, |
|
|
|
|
MetadataAwareAspectInstanceFactory aif, |
|
|
|
|
Method method, |
|
|
|
|
int declarationOrderInAspect, |
|
|
|
|
String aspectName) { |
|
|
|
|
|
|
|
|
|
this.declaredPointcut = ajexp; |
|
|
|
|
this.method = method; |
|
|
|
@ -72,15 +75,16 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
if (aif.getAspectMetadata().isLazilyInstantiated()) { |
|
|
|
|
// Static part of the pointcut is a lazy type.
|
|
|
|
|
Pointcut preInstantiationPointcut = |
|
|
|
|
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); |
|
|
|
|
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); |
|
|
|
|
|
|
|
|
|
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
|
|
|
|
|
// If it's not a dynamic pointcut, it may be optimized out
|
|
|
|
|
// by the Spring AOP infrastructure after the first evaluation.
|
|
|
|
|
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif); |
|
|
|
|
this.pointcut = |
|
|
|
|
new PerTargetInstantiationModelPointcut( |
|
|
|
|
this.declaredPointcut, preInstantiationPointcut, aif); |
|
|
|
|
this.lazy = true; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
// A singleton aspect.
|
|
|
|
|
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); |
|
|
|
|
this.pointcut = declaredPointcut; |
|
|
|
@ -88,10 +92,9 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change |
|
|
|
|
* depending on the state of the advice. |
|
|
|
|
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change depending on |
|
|
|
|
* the state of the advice. |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public Pointcut getPointcut() { |
|
|
|
@ -99,25 +102,21 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* This is only of interest for Spring AOP: AspectJ instantiation semantics |
|
|
|
|
* are much richer. In AspectJ terminology, all a return of {@code true} |
|
|
|
|
* means here is that the aspect is not a SINGLETON. |
|
|
|
|
* This is only of interest for Spring AOP: AspectJ instantiation semantics are much richer. In |
|
|
|
|
* AspectJ terminology, all a return of {@code true} means here is that the aspect is not a |
|
|
|
|
* SINGLETON. |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public boolean isPerInstance() { |
|
|
|
|
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Return the AspectJ AspectMetadata for this advisor. |
|
|
|
|
*/ |
|
|
|
|
/** Return the AspectJ AspectMetadata for this advisor. */ |
|
|
|
|
public AspectMetadata getAspectMetadata() { |
|
|
|
|
return this.aspectInstanceFactory.getAspectMetadata(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Lazily instantiate advice if necessary. |
|
|
|
|
*/ |
|
|
|
|
/** Lazily instantiate advice if necessary. */ |
|
|
|
|
@Override |
|
|
|
|
public synchronized Advice getAdvice() { |
|
|
|
|
if (this.instantiatedAdvice == null) { |
|
|
|
@ -136,10 +135,9 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
return (this.instantiatedAdvice != null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { |
|
|
|
|
return this.atAspectJAdvisorFactory.getAdvice( |
|
|
|
|
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); |
|
|
|
|
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() { |
|
|
|
@ -182,17 +180,15 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Duplicates some logic from getAdvice, but importantly does not force |
|
|
|
|
* creation of the advice. |
|
|
|
|
* Duplicates some logic from getAdvice, but importantly does not force creation of the advice. |
|
|
|
|
*/ |
|
|
|
|
private void determineAdviceType() { |
|
|
|
|
AbstractAspectJAdvisorFactory.AspectJAnnotation<?> aspectJAnnotation = |
|
|
|
|
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); |
|
|
|
|
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); |
|
|
|
|
if (aspectJAnnotation == null) { |
|
|
|
|
this.isBeforeAdvice = false; |
|
|
|
|
this.isAfterAdvice = false; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
switch (aspectJAnnotation.getAnnotationType()) { |
|
|
|
|
case AtAfter: |
|
|
|
|
case AtAfterReturning: |
|
|
|
@ -212,20 +208,20 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public String toString() { |
|
|
|
|
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() + |
|
|
|
|
"]; advice method [" + this.method + "]; perClauseKind=" + |
|
|
|
|
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind(); |
|
|
|
|
|
|
|
|
|
return "InstantiationModelAwarePointcutAdvisor: expression [" |
|
|
|
|
+ getDeclaredPointcut().getExpression() |
|
|
|
|
+ "]; advice method [" |
|
|
|
|
+ this.method |
|
|
|
|
+ "]; perClauseKind=" |
|
|
|
|
+ this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Pointcut implementation that changes its behaviour when the advice is instantiated. |
|
|
|
|
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might |
|
|
|
|
* be optimized out if it does not at first match statically. |
|
|
|
|
* Pointcut implementation that changes its behaviour when the advice is instantiated. Note that |
|
|
|
|
* this is a <i>dynamic</i> pointcut. Otherwise it might be optimized out if it does not at first |
|
|
|
|
* match statically. |
|
|
|
|
*/ |
|
|
|
|
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut { |
|
|
|
|
|
|
|
|
@ -235,20 +231,24 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
|
|
|
|
|
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory; |
|
|
|
|
|
|
|
|
|
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut, |
|
|
|
|
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) { |
|
|
|
|
private PerTargetInstantiationModelPointcut( |
|
|
|
|
AspectJExpressionPointcut declaredPointcut, |
|
|
|
|
Pointcut preInstantiationPointcut, |
|
|
|
|
MetadataAwareAspectInstanceFactory aspectInstanceFactory) { |
|
|
|
|
this.declaredPointcut = declaredPointcut; |
|
|
|
|
this.preInstantiationPointcut = preInstantiationPointcut; |
|
|
|
|
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) { |
|
|
|
|
this.aspectInstanceFactory = (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory; |
|
|
|
|
this.aspectInstanceFactory = |
|
|
|
|
(LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public boolean matches(Method method, Class<?> targetClass) { |
|
|
|
|
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
|
|
|
|
|
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) || |
|
|
|
|
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass); |
|
|
|
|
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on
|
|
|
|
|
// either pointcut
|
|
|
|
|
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) |
|
|
|
|
|| this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@ -261,5 +261,4 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
|
|
|
|
return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|