技术标签: spring aop spring学习笔记
前面介绍了advice以及adivce是怎么进入到目标的调用链中进行调用的,不过在spring中advice都是包在advisor中进行注册的,而pointcut则是切面,主要用来匹配对应的方法是否需要进行Advice增强,而targetSource则是代理的目标源,这个源可以是单例,实例池等。
可以看到Advisor的下层主要是两个子接口IntrodutionAdvisor和PointcutAdvisor以及一个PrototypePlaceholderAdvisor。
这个ProtoTypePlaceHolderAdvisor中没有advice,只是维护了一个beanName以便ProxyFactoryBean在获取prototype类型的代理类时能从容器中获取对应的Advisor
Advisor其下的一种是IntroductionAdvisor一种是PointcutAdvisor。
对于IntroductionAdvisor一个是所有的都匹配都过的DefaultIntrodcutionAdvisor,另一种主要是对 @DeclareParents 这个注解的实现。
另一种就是PointcutAdvisor,这个接口主要是利用Pointcut来过滤目标bean是否需要进行Advice的增强。
方式 | advisor |
---|---|
<aop:advice/> | AspectJPointcutAdvisor |
<aop:advice><declare-parents/><aop:advice/> | DeclareParentsAdvisor |
<aop:advisor/> | DefaultBeanFactoryPointcutAdvisor |
@Before | InstantiationModelAwarePointcutAdvisorImpl |
@After | InstantiationModelAwarePointcutAdvisorImpl |
@AfterThrowing | InstantiationModelAwarePointcutAdvisorImpl |
@AfterReturning | InstantiationModelAwarePointcutAdvisorImpl |
@Around | InstantiationModelAwarePointcutAdvisorImpl |
@DeclareParents | DeclareParentsAdvisor |
public interface Advisor {
//返回这个advisor中的advice
Advice getAdvice();
//是否和特定的实例关联,不过spring框架中没有对这个方法进行调用,所有的实现类都是返回true
boolean isPerInstance();
}
IntroductionAdvisor接口继承了Advisor和IntroductionInfo,这个IntroductionInfo则是提供描述一个introduction的详细信息,主要是其需要实现的接口。
IntroductionAdvisor主要有两个方法,一个是getClassFilter() 用于获取获取对应的类过滤器。另一个方法则是validateInterfaces() 用于验证其Advice能否对IntroductionInfo中需要实现的接口进行实现。
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
//返回类过滤器,检查对应的类是否需要应用这个advisor中的advice
ClassFilter getClassFilter();
//验证IntrodutionInfo中的interface能否应用到对应的advice中
//这个在将IntroductionAdvisor加入到AdvisedSupport之前会调用
void validateInterfaces() throws IllegalArgumentException;
}
DefaultIntroductionAdvisor实现了三个接口IntroductionAdvisor,ClassFilter和Ordered,其对ClassFilter中的实现为直接返回true,并且对IntroductionAdvisor的getClasFilter() 的实现是返回自己。表明它注入到容器中则会对所有的bean进行增强。
而其维护了一个set来存储注册到这个Advisor中需要实现的Interface。如果其advice实现了IntroductionInfo的接口则会从Advice中获取。
它还实现了Ordered接口,对于AbstractAdvisorAutoProxyCreator找到的对应的Advisor链最终会进行排序,而其默认是LOWEST_PRECEDENCE则默认是放在调用链的第一个。
public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFilter, Ordered, Serializable {
//对应的advisor
private final Advice advice;
//对应需要实现的接口
private final Set<Class<?>> interfaces = new LinkedHashSet<Class<?>>();
//排序用的
private int order = Ordered.LOWEST_PRECEDENCE;
public DefaultIntroductionAdvisor(Advice advice) {
this(advice, (advice instanceof IntroductionInfo ? (IntroductionInfo) advice : null));
}
public DefaultIntroductionAdvisor(Advice advice, IntroductionInfo introductionInfo) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
if (introductionInfo != null) {
Class<?>[] introducedInterfaces = introductionInfo.getInterfaces();
if (introducedInterfaces.length == 0) {
throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces");
}
for (Class<?> ifc : introducedInterfaces) {
addInterface(ifc);
}
}
}
public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class<?> ifc) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
addInterface(ifc);
}
public void addInterface(Class<?> ifc) {
Assert.notNull(ifc, "Interface must not be null");
if (!ifc.isInterface()) {
throw new IllegalArgumentException("Specified class [" + ifc.getName() + "] must be an interface");
}
this.interfaces.add(ifc);
}
@Override
public Class<?>[] getInterfaces() {
return ClassUtils.toClassArray(this.interfaces);
}
@Override
public void validateInterfaces() throws IllegalArgumentException {
for (Class<?> ifc : this.interfaces) {
if (this.advice instanceof DynamicIntroductionAdvice &&
!((DynamicIntroductionAdvice) this.advice).implementsInterface(ifc)) {
throw new IllegalArgumentException("DynamicIntroductionAdvice [" + this.advice + "] " +
"does not implement interface [" + ifc.getName() + "] specified for introduction");
}
}
}
@Override
public boolean matches(Class<?> clazz) {
return true;
}
...
}
这个Advisor是注解**@DeclareParents最终注册的Advisor**,@DeclareParents配置中的value和defaultImpl则为其构造函数中的typePattern和defaultImpl,而其对应的interfaceType则是其配置的Field的类型。
其·对应的advice是DelegatePerTargetObjectIntroductionInterceptor和DelegatingIntroductionInterceptor两种,为IntroductionInterceptor的两种默认实现的advice。
public class DeclareParentsAdvisor implements IntroductionAdvisor {
private final Advice advice;
private final Class<?> introducedInterface;
private final ClassFilter typePatternClassFilter;
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
this(interfaceType, typePattern,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
}
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(delegateRef));
}
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, IntroductionInterceptor interceptor) {
this.advice = interceptor;
this.introducedInterface = interfaceType;
// Excludes methods implemented.
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
ClassFilter exclusion = new ClassFilter() {
@Override
public boolean matches(Class<?> clazz) {
return !introducedInterface.isAssignableFrom(clazz);
}
};
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
}
@Override
public ClassFilter getClassFilter() {
return this.typePatternClassFilter;
}
@Override
public void validateInterfaces() throws IllegalArgumentException {
// Do nothing
}
@Override
public boolean isPerInstance() {
return true;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public Class<?>[] getInterfaces() {
return new Class<?>[] {
this.introducedInterface};
}
}
PointcutAdvisor继承了Advisor,并提供了一个getPointcut()获取Pointcut,而Pointcut这个接口中提供了获取ClassFilter和MethodMatcher的方法,表明PointcutAdvisor是方法级别的,而上面的IntroductionAdvisor的粒度只能到类级别。
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
PointcutAdvisor的子类主要是对于其Advice和Pointcut的种类以及获取方式的不同而有了不同的实现,下图展示了其对应的抽象类和实现类的具体的功能。
除了上面的相关的实现外,PointcutAdvisor还有一个子接口,InstantiationModelAwarePointcutAdvisor,这个子接口有一个唯一的实现InstantiationModelAwarePointcutAdvisorImpl,它是通过注解形式注入的最终的Advisor,这个接口提供了懒加载Advice的策略,所以提供了是否是懒加载以及advice是否被实例化的方法。
public interface InstantiationModelAwarePointcutAdvisor extends PointcutAdvisor {
//是否是懒加载
boolean isLazy();
//advice是否已经被实现了的
boolean isAdviceInstantiated();
}
这个实例不是由BeanFactory实现的,而是ReflectiveAspectJAdvisorFactory实现的。它主要实现了InstantiationModelAwarePointcutAdvisor和AspectJPrecedenceInformation这两个接口,其中AspectJPrecedenceInformation主要是进行advisor排序时需要使用的接口,AbstractAspectJAdvice也实现了这个接口。
这个Advisor的对应的Advice是AspectJAdvisorFactory 进行实现的,其Pointcut是PerTargetInstantiationModelPointcut ,这个Pointcut是一个动态的Pointcut,其主要作用是在aspectJInstance还没有实例化时利用perClausePointcut进行静态匹配。而在运行中再用定义好的AspectJExpressionPointcut进行匹配。
class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
//声明的pointcut
private final AspectJExpressionPointcut declaredPointcut;
//用于序列化获取对应的方法
private final Class<?> declaringClass;
//用于序列化后获取对应的Method对象
private final String methodName;
//用于序列化后获取对应的Method对象
private final Class<?>[] parameterTypes;
//对应的aspectJAdviceMethod
private transient Method aspectJAdviceMethod;
//利用这个factory创建advice
private final AspectJAdvisorFactory aspectJAdvisorFactory;
//从这个factory中获取instance
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
//用于advisor的比较
private final int declarationOrder;
//用于advisor的比较
private final String aspectName;
//最终是以的pointcut
private final Pointcut pointcut;
//对应的切面实例是否是懒加载
private final boolean lazy;
//实现出来的advice
private Advice instantiatedAdvice;
//是否是前置advice
private Boolean isBeforeAdvice;
//是否是后置advice
private Boolean isAfterAdvice;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
//对于在Aspect对象是懒加的情况则加上在@Aspect中配置的表达式匹配
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
//利用aspectJAdvisorFactory实例化对应的Advice
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
private final AspectJExpressionPointcut declaredPointcut;
private final Pointcut preInstantiationPointcut;
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
this.declaredPointcut = declaredPointcut;
this.preInstantiationPointcut = preInstantiationPointcut;
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
this.aspectInstanceFactory = (LazySingletonAspectInstanceFactoryDecorator) aspectInstanceFactory;
}
}
//静态匹配时在aspectJ还没有实例化时加上
//利用@Aspect中prethis或者pretarget等配置的表达式以进行匹配,
@Override
public boolean matches(Method method, Class<?> targetClass) {
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
}
//运行时匹配,需要对应的aspect实例化才能匹配成功。
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
}
private boolean isAspectMaterialized() {
return (this.aspectInstanceFactory == null || this.aspectInstanceFactory.isMaterialized());
}
}
}
targetSource是代理目标的获取源,spring实现了很多种类型的targetSource,其扩展的方式主要是获取的位置以及对应target的生命周期
TargetSource 继承了TargetClassAware,Advised接口也实现了这个接口,不过其实现了AdvisedSupport类也是用其对应的targetSource获取对应的class。
public interface TargetSource extends TargetClassAware {
//返回目标的class
@Override
Class<?> getTargetClass();
//对应的target是否是否改变
boolean isStatic();
//获取target对象
Object getTarget() throws Exception;
//释放target对象
void releaseTarget(Object target) throws Exception;
}
targetSource
AbstractBeanFactoryBasedTargetSource: 这个抽象类主要实现了BeanFactoryAware接口,并维护了beanFactory,它的target实例是从beanFactory获取。
AbstractPrototypeBasedTargetSource: 主要是验证了target的beanName对应的bean在beanFactory的类型是prototype。
AbstractPoolingTargetSource: 这个抽象类实现了PoolConfig,表示是池类的targetSource 。
ProtoTypeTargetSource: 直接从beanFactory中获取prototype类型的bean作为target。
ThreadLocalTargetSource: 将获取的bean存储在ThreadLocal ,它在releaseTarget的操作的时候不会从ThreadLocal中释放对应的target。
LazyInitTargetSource: 在调用getTarget()方法时才从beanFactory中获取对应的bean存储在本地对象中。
SimpleBeanTargetSource: 直接从beanFactory中获取对应的bean作为target。
AbstractLazyCreationTargetSource: 在调用getTarget() 才调用其抽象方法createObject() 获取对应的target。
AbstractRefreshableTargetSource: 根据时间会刷新target。
EmptyTargetSource: 直接返回Null
HotswappableTargetSource: 提供一个**swap()**方法可以替换内部的target。
SingletonTargetSource: 内部维护了一个唯一的对象作为target。
Pointcut主要是用来匹配对应的切点,主要是提供了ClassFilter和MethodMatcher两个匹配接口,分别对目标的类以及方法进行匹配,其扩展主要是在方法的匹配上进行的,分别在运行时,静态。然后匹配的位置主要扩展方式是匹配注解,调用栈,方法名等。而匹配的方式的扩展主要有利用正则 ,AspectJ表达式等进行匹配。
可以看到,Pointcut主要是提供了ClassFilter和MethodMatcher两个匹配起,具体的匹配规则则委托给了这两个匹配器。
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
Pointcut
AnnotationMatchingPointcut: 主要是匹配对应的class 和method的注解有没有配置的注解。
ComposablePointcut: 主要是可以和其他的ClassFilter和MethodMatcher,pointcut做与或者或的操作,将它们组合起一个ComposablePointcut操作。
ControlFlowPoint: 从调用栈中找对应的method的匹配(匹配的是类名和方法名)。
DynamicMethodMatcherPointcut: 继承了DynamicMethodMatcher,其ClassFilter直接为true。
StaticMethodMatcherPointcut: 继承了StaticMethodMatcher ,对应的ClassFilter为true,只进行静态匹配对应的目标的method。
AbstractRegxpMethodPointcut: 维护了匹配正则字符串数组和过滤正则字符串数组。
GetterPointcut: 匹配对应的方法名是否是以get开头的。
NameMatchMethodPointcut: 使用*和.来匹配目标方法名。
SetterPointcut: 匹配对应的方法名是否是以set开头的。
StaticMethodPointcutAdvisor: 匹配静态方法的advisor的抽象类。
TruePointcut: calssFilter和MethodMatcher都返回true 。
ExpressionPointcut: 提供了一个**getExpression() **方法
AbstractExpressionPointcut: 维护了一个字符串的表达式
AspectJExpressionPointcut: 利用AspectJ表达式进行匹配。
AspectJExpressionPointcut是用spring-aop常用的pointcut,在利用@Before,
<aop:advice/>等方式注入advisor时其pointcut都是AspectJExpressionPointcut。
所以详细介绍一下这种pointcut。
AspectJExpressionPointcut的是将其对应的表达式转换为PointcutExpression,其对method的匹配结果为ShadowMatch,并利用shadowMatchCache 进行了缓存,而其对应的运行时的匹配则是利用ShadowMatch来进行匹配。
可以看到AspectJExpressionPointcut实现了ClassFilter和IntroductionAwareMethodMatcher以及BeanFactoryAware 三个接口,可以看到其对应的MethodMatcher是IntroductionAwareMethodMatcher,这个接口,这个接口定义了一个需要参数hasIntroductions表示其调用链中有没有IntroduceAdvice。
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
//支持的语法
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
static {
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
}
// 对应的aspect的class
private Class<?> pointcutDeclarationScope;
//构建pointcutExpression的参数
private String[] pointcutParameterNames = new String[0];
//构建pointcutExpression的参数类型
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
//beanFactory主要是
private BeanFactory beanFactory;
//用来构建pointcutClassLoader
private transient ClassLoader pointcutClassLoader;
//aspectJ中的匹配表达式,有点类似jdk中的Pattern
private transient PointcutExpression pointcutExpression;
//为每个method维护了一个ShadowMatch缓存,这个ShadowMatch有点类似jdk中的Matcher
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
...
}
ClassFilter 的match方法实现匹配类。可以看到它是用PointcutExpression的借助couldMatchJoinPointsInType() 方法来进行匹配的,可以看到它在匹配出现ReflectionWorldException异常时会利用fallbackExpression来尝试匹配一次,这个fallbackExpression与原来的pointcutExpression不同之处在于它们的classLoader是不一样的,pointcutExpression默认用的是beanFactory的,而fallbackExpression则是用的pointcutDeclarationScope的classLoader。
@Override
public boolean matches(Class<?> targetClass) {
checkReadyToMatch();
try {
try {
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
if (fallbackExpression != null) {
return fallbackExpression.couldMatchJoinPointsInType(targetClass);
}
}
}
catch (Throwable ex) {
logger.debug("PointcutExpression matching rejected target class", ex);
}
return false;
}
主要是获取对应的ShadowMatch来进行匹配,对于立刻能判断成功的直接返回判断结果,而对于target的instanceof这些表达式则可以直接判断,因为spring的targetClass在运行时是不会发生改变。
@Override
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
//实例化pointcutExpression
checkReadyToMatch();
//获取其目标方法,这个method对象的对应的class可能不是targetClass
//尽可能找到目标class中这个method的对象
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
//获取ShadowMatch
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
if (shadowMatch.alwaysMatches()) {
return true;
}
else if (shadowMatch.neverMatches()) {
return false;
}
else {
// the maybe case
if (beanHasIntroductions) {
return true;
}
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
//这里主要是测试表达式中instanceof这种判断,因为在spring-aop中的targetSource在运行时是不会发生改变,因此在静态匹配中就可以过滤掉那些表达式中instanceOf不匹配的target
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
}
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return matches(method, targetClass, false);
}
方法动态的匹配主要是在运行时获取对应的this,target和args对象进行匹配,而对this和target对象的获取主要是依赖ExposeInvocationInterceptor这个advice将其ThreadLocal中进行获取。
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
checkReadyToMatch();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
ProxyMethodInvocation pmi = null;
Object targetObject = null;
Object thisObject = null;
//从当前调用链中的暴露出来的代理对象获取this和target
try {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
targetObject = mi.getThis();
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
pmi = (ProxyMethodInvocation) mi;
thisObject = pmi.getProxy();
}
catch (IllegalStateException ex) {
// No current invocation...
if (logger.isDebugEnabled()) {
logger.debug("Could not access current invocation - matching with limited context: " + ex);
}
}
try {
//匹配this,target和args
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
if (pmi != null) {
//匹配this的instanceof数据
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
if (joinPointMatch.matches()) {
//将JoinPointMatch放入ProxyMethodInvocation的userAttributes中,对应的AbstractAspectJAdvice中的aspectJAdviceMethod的JoinPointMatch参数就是此处
bindParameters(pmi, joinPointMatch);
}
}
//返回运行时匹配的结果
return joinPointMatch.matches();
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
" - falling back to non-match", ex);
}
return false;
}
}
获取shadowMatch主要是先利用targetMethod获取,如果其没有获取则利用originalMethod获取,但是最终存储到cache的key是targetMethod
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
synchronized (this.shadowMatchCache) {
PointcutExpression fallbackExpression = null;
Method methodToMatch = targetMethod;
shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
try {
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex) {
try {
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
if (shadowMatch == null && targetMethod != originalMethod) {
methodToMatch = originalMethod;
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex3) {
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
try {
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex4) {
fallbackExpression = null;
}
}
}
}
catch (Throwable ex) {
// Possibly AspectJ 1.8.10 encountering an invalid signature
logger.debug("PointcutExpression matching rejected target method", ex);
fallbackExpression = null;
}
if (shadowMatch == null) {
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
}
else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
shadowMatch = new DefensiveShadowMatch(shadowMatch,
fallbackExpression.matchesMethodExecution(methodToMatch));
}
this.shadowMatchCache.put(targetMethod, shadowMatch);
}
}
}
return shadowMatch;
}
名称 | 配置类型 | 匹配类型 |
---|---|---|
execution | 方法表达式 | 匹配方法执行的连接点 |
this | 类型全限定名 | 匹配当前的代理对象 |
target | 类型全限定名 | 匹配目标对象 |
args | 参数类型列表 | 匹配执行方法传入的参数的类型 |
within | 类型表达式 | 匹配执行对应类型表达式下的方法 |
@target | 注解类型 | 匹配目标是否有对应的注解 |
@within | 注解类型 | 任何目标对象对应的类型是否有对应的注解 |
@args | 注解列表 | 匹配执行方法传入的参数是否带有指定注解 |
@annotation | 注解类型 | 匹配当前执行方法持有指定注解的方法 |
文章浏览阅读2.5w次,点赞6次,收藏50次。官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。_docker菜鸟教程
文章浏览阅读5.7k次,点赞3次,收藏14次。该如何避免的,今天小编给大家推荐两个下载Windows系统官方软件的资源网站,可以杜绝软件捆绑等行为。该站提供了丰富的Windows官方技术资源,比较重要的有MSDN技术资源文档库、官方工具和资源、应用程序、开发人员工具(Visual Studio 、SQLServer等等)、系统镜像、设计人员工具等。总的来说,这两个都是非常优秀的Windows系统镜像资源站,提供了丰富的Windows系统镜像资源,并且保证了资源的纯净和安全性,有需要的朋友可以去了解一下。这个非常实用的资源网站的创建者是国内的一个网友。_msdn我告诉你
文章浏览阅读1.2k次。vue2封装对话框el-dialog组件_
文章浏览阅读4.7k次,点赞5次,收藏6次。MFC 文本框换行 标签: it mfc 文本框1.将Multiline属性设置为True2.换行是使用"\r\n" (宽字符串为L"\r\n")3.如果需要编辑并且按Enter键换行,还要将 Want Return 设置为 True4.如果需要垂直滚动条的话将Vertical Scroll属性设置为True,需要水平滚动条的话将Horizontal Scroll属性设_c++ mfc同一框内输入二行怎么换行
文章浏览阅读832次。检查Linux是否是否开启所需端口,默认为6379,若未打开,将其开启:以root用户执行iptables -I INPUT -p tcp --dport 6379 -j ACCEPT如果还是未能解决,修改redis.conf,修改主机地址:bind 192.168.85.**;然后使用该配置文件,重新启动Redis服务./redis-server redis.conf..._redis-server doesn't support auth command or ismisconfigured. try
文章浏览阅读4.9k次。济大数电实验报告_数据选择器及其应用
文章浏览阅读236次。1研究内容消费在生产中占据十分重要的地位,是生产的最终目的和动力,是保持省内经济稳定快速发展的核心要素。预测河南省社会消费品零售总额,是进行宏观经济调控和消费体制改变创新的基础,是河南省内人民对美好的全面和谐社会的追求的要求,保持河南省经济稳定和可持续发展具有重要意义。本文建立灰色预测模型,利用MATLAB软件,预测出2019年~2023年河南省社会消费品零售总额预测值分别为21881...._灰色预测模型用什么软件
文章浏览阅读1.2k次。12.4-在Qt中使用Log4Qt输出Log文件,看这一篇就足够了一、为啥要使用第三方Log库,而不用平台自带的Log库二、Log4j系列库的功能介绍与基本概念三、Log4Qt库的基本介绍四、将Log4qt组装成为一个单独模块五、使用配置文件的方式配置Log4Qt六、使用代码的方式配置Log4Qt七、在Qt工程中引入Log4Qt库模块的方法八、获取示例中的源代码一、为啥要使用第三方Log库,而不用平台自带的Log库首先要说明的是,在平时开发和调试中开发平台自带的“打印输出”已经足够了。但_log4qt
文章浏览阅读786次。全局观思维模型,一个教我们由点到线,由线到面,再由面到体,不断的放大格局去思考问题的思维模型。_计算机中对于全局观的
文章浏览阅读330次。一、CountDownLatch介绍CountDownLatch采用减法计算;是一个同步辅助工具类和CyclicBarrier类功能类似,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。二、CountDownLatch俩种应用场景: 场景一:所有线程在等待开始信号(startSignal.await()),主流程发出开始信号通知,既执行startSignal.countDown()方法后;所有线程才开始执行;每个线程执行完发出做完信号,既执行do..._countdownluach于cyclicbarrier的用法
文章浏览阅读508次。Prometheus 算是一个全能型选手,原生支持容器监控,当然监控传统应用也不是吃干饭的,所以就是容器和非容器他都支持,所有的监控系统都具备这个流程,_-自动化监控系统prometheus&grafana实战
文章浏览阅读4.7k次。输入关键字,可以通过键盘的搜索按钮完成搜索功能。_react search