|
|
@ -16,256 +16,249 @@ |
|
|
|
|
|
|
|
|
|
|
|
package com.fr.third.springframework.aop.aspectj; |
|
|
|
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.aspectj.lang.reflect.PerClauseKind; |
|
|
|
|
|
|
|
|
|
|
|
import com.fr.third.springframework.aop.Pointcut; |
|
|
|
import com.fr.third.springframework.aop.Pointcut; |
|
|
|
import com.fr.third.springframework.aop.support.DynamicMethodMatcherPointcut; |
|
|
|
import com.fr.third.springframework.aop.support.DynamicMethodMatcherPointcut; |
|
|
|
import com.fr.third.springframework.aop.support.Pointcuts; |
|
|
|
import com.fr.third.springframework.aop.support.Pointcuts; |
|
|
|
|
|
|
|
import org.aopalliance.aop.Advice; |
|
|
|
|
|
|
|
|
|
|
|
import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAfter; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAfterReturning; |
|
|
|
|
|
|
|
import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAfterThrowing; |
|
|
|
|
|
|
|
import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtAround; |
|
|
|
|
|
|
|
import static com.fr.third.springframework.aop.aspectj.AbstractAspectJAdvisorFactory.AspectJAnnotationType.AtPointcut; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Internal implementation of AspectJPointcutAdvisor. |
|
|
|
* Internal implementation of AspectJPointcutAdvisor. Note that there will be one instance of this |
|
|
|
* Note that there will be one instance of this advisor for each target method. |
|
|
|
* advisor for each target method. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Rod Johnson |
|
|
|
* @author Rod Johnson |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @since 2.0 |
|
|
|
* @since 2.0 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
class InstantiationModelAwarePointcutAdvisorImpl |
|
|
|
class InstantiationModelAwarePointcutAdvisorImpl |
|
|
|
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { |
|
|
|
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { |
|
|
|
|
|
|
|
|
|
|
|
private final AspectJExpressionPointcut declaredPointcut; |
|
|
|
private final AspectJExpressionPointcut declaredPointcut; |
|
|
|
|
|
|
|
|
|
|
|
private Pointcut pointcut; |
|
|
|
private Pointcut pointcut; |
|
|
|
|
|
|
|
|
|
|
|
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; |
|
|
|
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; |
|
|
|
|
|
|
|
|
|
|
|
private final Method method; |
|
|
|
private final Method method; |
|
|
|
|
|
|
|
|
|
|
|
private final boolean lazy; |
|
|
|
private final boolean lazy; |
|
|
|
|
|
|
|
|
|
|
|
private final AspectJAdvisorFactory atAspectJAdvisorFactory; |
|
|
|
private final AspectJAdvisorFactory atAspectJAdvisorFactory; |
|
|
|
|
|
|
|
|
|
|
|
private Advice instantiatedAdvice; |
|
|
|
private Advice instantiatedAdvice; |
|
|
|
|
|
|
|
|
|
|
|
private int declarationOrder; |
|
|
|
private int declarationOrder; |
|
|
|
|
|
|
|
|
|
|
|
private String aspectName; |
|
|
|
private String aspectName; |
|
|
|
|
|
|
|
|
|
|
|
private Boolean isBeforeAdvice; |
|
|
|
private Boolean isBeforeAdvice; |
|
|
|
|
|
|
|
|
|
|
|
private Boolean isAfterAdvice; |
|
|
|
private Boolean isAfterAdvice; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public InstantiationModelAwarePointcutAdvisorImpl( |
|
|
|
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp, |
|
|
|
AspectJAdvisorFactory af, |
|
|
|
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { |
|
|
|
AspectJExpressionPointcut ajexp, |
|
|
|
|
|
|
|
MetadataAwareAspectInstanceFactory aif, |
|
|
|
this.declaredPointcut = ajexp; |
|
|
|
Method method, |
|
|
|
this.method = method; |
|
|
|
int declarationOrderInAspect, |
|
|
|
this.atAspectJAdvisorFactory = af; |
|
|
|
String aspectName) { |
|
|
|
this.aspectInstanceFactory = aif; |
|
|
|
|
|
|
|
this.declarationOrder = declarationOrderInAspect; |
|
|
|
this.declaredPointcut = ajexp; |
|
|
|
this.aspectName = aspectName; |
|
|
|
this.method = method; |
|
|
|
|
|
|
|
this.atAspectJAdvisorFactory = af; |
|
|
|
if (aif.getAspectMetadata().isLazilyInstantiated()) { |
|
|
|
this.aspectInstanceFactory = aif; |
|
|
|
// Static part of the pointcut is a lazy type.
|
|
|
|
this.declarationOrder = declarationOrderInAspect; |
|
|
|
Pointcut preInstantiationPointcut = |
|
|
|
this.aspectName = aspectName; |
|
|
|
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); |
|
|
|
|
|
|
|
|
|
|
|
if (aif.getAspectMetadata().isLazilyInstantiated()) { |
|
|
|
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
|
|
|
|
// Static part of the pointcut is a lazy type.
|
|
|
|
// If it's not a dynamic pointcut, it may be optimized out
|
|
|
|
Pointcut preInstantiationPointcut = |
|
|
|
// by the Spring AOP infrastructure after the first evaluation.
|
|
|
|
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); |
|
|
|
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif); |
|
|
|
|
|
|
|
this.lazy = true; |
|
|
|
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
|
|
|
|
} |
|
|
|
// If it's not a dynamic pointcut, it may be optimized out
|
|
|
|
else { |
|
|
|
// by the Spring AOP infrastructure after the first evaluation.
|
|
|
|
// A singleton aspect.
|
|
|
|
this.pointcut = |
|
|
|
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); |
|
|
|
new PerTargetInstantiationModelPointcut( |
|
|
|
this.pointcut = declaredPointcut; |
|
|
|
this.declaredPointcut, preInstantiationPointcut, aif); |
|
|
|
this.lazy = false; |
|
|
|
this.lazy = true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
} |
|
|
|
// A singleton aspect.
|
|
|
|
|
|
|
|
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); |
|
|
|
|
|
|
|
this.pointcut = declaredPointcut; |
|
|
|
/** |
|
|
|
this.lazy = false; |
|
|
|
* 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() { |
|
|
|
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change depending on |
|
|
|
return this.pointcut; |
|
|
|
* the state of the advice. |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
@Override |
|
|
|
/** |
|
|
|
public Pointcut getPointcut() { |
|
|
|
* This is only of interest for Spring AOP: AspectJ instantiation semantics |
|
|
|
return this.pointcut; |
|
|
|
* are much richer. In AspectJ terminology, all a return of {@code true} |
|
|
|
} |
|
|
|
* means here is that the aspect is not a SINGLETON. |
|
|
|
|
|
|
|
*/ |
|
|
|
/** |
|
|
|
@Override |
|
|
|
* This is only of interest for Spring AOP: AspectJ instantiation semantics are much richer. In |
|
|
|
public boolean isPerInstance() { |
|
|
|
* AspectJ terminology, all a return of {@code true} means here is that the aspect is not a |
|
|
|
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON); |
|
|
|
* SINGLETON. |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
@Override |
|
|
|
/** |
|
|
|
public boolean isPerInstance() { |
|
|
|
* Return the AspectJ AspectMetadata for this advisor. |
|
|
|
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON); |
|
|
|
*/ |
|
|
|
} |
|
|
|
public com.fr.third.aspectj.lang.annotation.AspectMetadata getAspectMetadata() { |
|
|
|
|
|
|
|
return this.aspectInstanceFactory.getAspectMetadata(); |
|
|
|
/** 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 |
|
|
|
@Override |
|
|
|
public synchronized Advice getAdvice() { |
|
|
|
public synchronized Advice getAdvice() { |
|
|
|
if (this.instantiatedAdvice == null) { |
|
|
|
if (this.instantiatedAdvice == null) { |
|
|
|
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); |
|
|
|
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); |
|
|
|
} |
|
|
|
} |
|
|
|
return this.instantiatedAdvice; |
|
|
|
return this.instantiatedAdvice; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean isLazy() { |
|
|
|
public boolean isLazy() { |
|
|
|
return this.lazy; |
|
|
|
return this.lazy; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public synchronized boolean isAdviceInstantiated() { |
|
|
|
public synchronized boolean isAdviceInstantiated() { |
|
|
|
return (this.instantiatedAdvice != null); |
|
|
|
return (this.instantiatedAdvice != null); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { |
|
|
|
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { |
|
|
|
return this.atAspectJAdvisorFactory.getAdvice( |
|
|
|
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() { |
|
|
|
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() { |
|
|
|
return this.aspectInstanceFactory; |
|
|
|
return this.aspectInstanceFactory; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public AspectJExpressionPointcut getDeclaredPointcut() { |
|
|
|
public AspectJExpressionPointcut getDeclaredPointcut() { |
|
|
|
return this.declaredPointcut; |
|
|
|
return this.declaredPointcut; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public int getOrder() { |
|
|
|
public int getOrder() { |
|
|
|
return this.aspectInstanceFactory.getOrder(); |
|
|
|
return this.aspectInstanceFactory.getOrder(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String getAspectName() { |
|
|
|
public String getAspectName() { |
|
|
|
return this.aspectName; |
|
|
|
return this.aspectName; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public int getDeclarationOrder() { |
|
|
|
public int getDeclarationOrder() { |
|
|
|
return this.declarationOrder; |
|
|
|
return this.declarationOrder; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean isBeforeAdvice() { |
|
|
|
public boolean isBeforeAdvice() { |
|
|
|
if (this.isBeforeAdvice == null) { |
|
|
|
if (this.isBeforeAdvice == null) { |
|
|
|
determineAdviceType(); |
|
|
|
determineAdviceType(); |
|
|
|
} |
|
|
|
} |
|
|
|
return this.isBeforeAdvice; |
|
|
|
return this.isBeforeAdvice; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean isAfterAdvice() { |
|
|
|
public boolean isAfterAdvice() { |
|
|
|
if (this.isAfterAdvice == null) { |
|
|
|
if (this.isAfterAdvice == null) { |
|
|
|
determineAdviceType(); |
|
|
|
determineAdviceType(); |
|
|
|
} |
|
|
|
} |
|
|
|
return this.isAfterAdvice; |
|
|
|
return this.isAfterAdvice; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 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 = |
|
|
|
private void determineAdviceType() { |
|
|
|
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); |
|
|
|
AbstractAspectJAdvisorFactory.AspectJAnnotation<?> aspectJAnnotation = |
|
|
|
if (aspectJAnnotation == null) { |
|
|
|
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); |
|
|
|
this.isBeforeAdvice = false; |
|
|
|
if (aspectJAnnotation == null) { |
|
|
|
this.isAfterAdvice = false; |
|
|
|
this.isBeforeAdvice = false; |
|
|
|
} else { |
|
|
|
this.isAfterAdvice = false; |
|
|
|
switch (aspectJAnnotation.getAnnotationType()) { |
|
|
|
} |
|
|
|
case AtAfter: |
|
|
|
else { |
|
|
|
case AtAfterReturning: |
|
|
|
switch (aspectJAnnotation.getAnnotationType()) { |
|
|
|
case AtAfterThrowing: |
|
|
|
case AtAfter: |
|
|
|
this.isAfterAdvice = true; |
|
|
|
case AtAfterReturning: |
|
|
|
this.isBeforeAdvice = false; |
|
|
|
case AtAfterThrowing: |
|
|
|
break; |
|
|
|
this.isAfterAdvice = true; |
|
|
|
case AtAround: |
|
|
|
this.isBeforeAdvice = false; |
|
|
|
case AtPointcut: |
|
|
|
break; |
|
|
|
this.isAfterAdvice = false; |
|
|
|
case AtAround: |
|
|
|
this.isBeforeAdvice = false; |
|
|
|
case AtPointcut: |
|
|
|
break; |
|
|
|
this.isAfterAdvice = false; |
|
|
|
case AtBefore: |
|
|
|
this.isBeforeAdvice = false; |
|
|
|
this.isAfterAdvice = false; |
|
|
|
break; |
|
|
|
this.isBeforeAdvice = true; |
|
|
|
case AtBefore: |
|
|
|
} |
|
|
|
this.isAfterAdvice = false; |
|
|
|
} |
|
|
|
this.isBeforeAdvice = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
@Override |
|
|
|
} |
|
|
|
public String toString() { |
|
|
|
|
|
|
|
return "InstantiationModelAwarePointcutAdvisor: expression [" |
|
|
|
|
|
|
|
+ getDeclaredPointcut().getExpression() |
|
|
|
@Override |
|
|
|
+ "]; advice method [" |
|
|
|
public String toString() { |
|
|
|
+ this.method |
|
|
|
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() + |
|
|
|
+ "]; perClauseKind=" |
|
|
|
"]; advice method [" + this.method + "]; perClauseKind=" + |
|
|
|
+ this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind(); |
|
|
|
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 |
|
|
|
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut { |
|
|
|
* be optimized out if it does not at first match statically. |
|
|
|
|
|
|
|
*/ |
|
|
|
private final AspectJExpressionPointcut declaredPointcut; |
|
|
|
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut { |
|
|
|
|
|
|
|
|
|
|
|
private final Pointcut preInstantiationPointcut; |
|
|
|
private final AspectJExpressionPointcut declaredPointcut; |
|
|
|
|
|
|
|
|
|
|
|
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory; |
|
|
|
private final Pointcut preInstantiationPointcut; |
|
|
|
|
|
|
|
|
|
|
|
private PerTargetInstantiationModelPointcut( |
|
|
|
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory; |
|
|
|
AspectJExpressionPointcut declaredPointcut, |
|
|
|
|
|
|
|
Pointcut preInstantiationPointcut, |
|
|
|
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut, |
|
|
|
MetadataAwareAspectInstanceFactory aspectInstanceFactory) { |
|
|
|
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) { |
|
|
|
this.declaredPointcut = declaredPointcut; |
|
|
|
this.declaredPointcut = declaredPointcut; |
|
|
|
this.preInstantiationPointcut = preInstantiationPointcut; |
|
|
|
this.preInstantiationPointcut = preInstantiationPointcut; |
|
|
|
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) { |
|
|
|
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) { |
|
|
|
this.aspectInstanceFactory = |
|
|
|
this.aspectInstanceFactory = (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory; |
|
|
|
(LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean matches(Method method, Class<?> targetClass) { |
|
|
|
public boolean matches(Method method, Class<?> targetClass) { |
|
|
|
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
|
|
|
|
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on
|
|
|
|
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) || |
|
|
|
// either pointcut
|
|
|
|
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass); |
|
|
|
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) |
|
|
|
} |
|
|
|
|| this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass); |
|
|
|
|
|
|
|
} |
|
|
|
@Override |
|
|
|
|
|
|
|
public boolean matches(Method method, Class<?> targetClass, Object[] args) { |
|
|
|
@Override |
|
|
|
// This can match only on declared pointcut.
|
|
|
|
public boolean matches(Method method, Class<?> targetClass, Object[] args) { |
|
|
|
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)); |
|
|
|
// This can match only on declared pointcut.
|
|
|
|
} |
|
|
|
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)); |
|
|
|
|
|
|
|
} |
|
|
|
private boolean isAspectMaterialized() { |
|
|
|
|
|
|
|
return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized()); |
|
|
|
private boolean isAspectMaterialized() { |
|
|
|
} |
|
|
|
return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|