spring源码分享之Aop系列四(advisor,pointcut和targetSource)_isadviceinstantiated-程序员宅基地

技术标签: spring  aop  spring学习笔记  

前面介绍了advice以及adivce是怎么进入到目标的调用链中进行调用的,不过在spring中advice都是包在advisor中进行注册的,而pointcut则是切面,主要用来匹配对应的方法是否需要进行Advice增强,而targetSource则是代理的目标源,这个源可以是单例,实例池等。

Advisor

可以看到Advisor的下层主要是两个子接口IntrodutionAdvisorPointcutAdvisor以及一个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

IntroductionAdvisor接口继承了AdvisorIntroductionInfo,这个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

DefaultIntroductionAdvisor实现了三个接口IntroductionAdvisorClassFilterOrdered,其对ClassFilter中的实现为直接返回true,并且对IntroductionAdvisorgetClasFilter() 的实现是返回自己。表明它注入到容器中则会对所有的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;
	}

   ...
}

DeclareParentsAdvisor

这个Advisor是注解**@DeclareParents最终注册的Advisor**,@DeclareParents配置中的valuedefaultImpl则为其构造函数中的typePatterndefaultImpl,而其对应的interfaceType则是其配置的Field的类型。

其·对应的advice是DelegatePerTargetObjectIntroductionInterceptorDelegatingIntroductionInterceptor两种,为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

PointcutAdvisor继承了Advisor,并提供了一个getPointcut()获取Pointcut,而Pointcut这个接口中提供了获取ClassFilterMethodMatcher的方法,表明PointcutAdvisor是方法级别的,而上面的IntroductionAdvisor的粒度只能到类级别。

public interface PointcutAdvisor extends Advisor {
    
	Pointcut getPointcut();
}

PointcutAdvisor的子类主要是对于其AdvicePointcut的种类以及获取方式的不同而有了不同的实现,下图展示了其对应的抽象类和实现类的具体的功能。
在这里插入图片描述

InstantiationModelAwarePointcutAdvisor

除了上面的相关的实现外,PointcutAdvisor还有一个子接口,InstantiationModelAwarePointcutAdvisor,这个子接口有一个唯一的实现InstantiationModelAwarePointcutAdvisorImpl,它是通过注解形式注入的最终的Advisor,这个接口提供了懒加载Advice的策略,所以提供了是否是懒加载以及advice是否被实例化的方法。

public interface InstantiationModelAwarePointcutAdvisor extends PointcutAdvisor {
    
    //是否是懒加载
	boolean isLazy();
	//advice是否已经被实现了的
	boolean isAdviceInstantiated();
}
InstantiationModelAwarePointcutAdvisorImpl

这个实例不是由BeanFactory实现的,而是ReflectiveAspectJAdvisorFactory实现的。它主要实现了InstantiationModelAwarePointcutAdvisorAspectJPrecedenceInformation这两个接口,其中AspectJPrecedenceInformation主要是进行advisor排序时需要使用的接口,AbstractAspectJAdvice也实现了这个接口。

这个Advisor的对应的AdviceAspectJAdvisorFactory 进行实现的,其PointcutPerTargetInstantiationModelPointcut ,这个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

targetSource是代理目标的获取源,spring实现了很多种类型的targetSource,其扩展的方式主要是获取的位置以及对应target的生命周期
在这里插入图片描述

targetSource接口

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的子类

  • targetSource

    • AbstractBeanFactoryBasedTargetSource: 这个抽象类主要实现了BeanFactoryAware接口,并维护了beanFactory,它的target实例是从beanFactory获取。

      • AbstractPrototypeBasedTargetSource: 主要是验证了target的beanName对应的bean在beanFactory的类型是prototype。

        • AbstractPoolingTargetSource: 这个抽象类实现了PoolConfig,表示是池类的targetSource 。

          • CommonsPool2TargetSource: 利用apache的ObjectPool来存储对应的target对象,它实现了PooledObjectFactory,这个池中的对象还是从beanFactory中获取。
        • 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。

      • BeanFactoryRefreshableTargetSource: 他的target是从beanFactory中获取。
    • EmptyTargetSource: 直接返回Null

    • HotswappableTargetSource: 提供一个**swap()**方法可以替换内部的target。

    • SingletonTargetSource: 内部维护了一个唯一的对象作为target。

Pointcut

Pointcut主要是用来匹配对应的切点,主要是提供了ClassFilterMethodMatcher两个匹配接口,分别对目标的以及方法进行匹配,其扩展主要是在方法的匹配上进行的,分别在运行时,静态。然后匹配的位置主要扩展方式是匹配注解调用栈,方法名等。而匹配的方式的扩展主要有利用正则 ,AspectJ表达式等进行匹配。
在这里插入图片描述

Pointcut接口

可以看到,Pointcut主要是提供了ClassFilterMethodMatcher两个匹配起,具体的匹配规则则委托给了这两个匹配器。

public interface Pointcut {
    
	ClassFilter getClassFilter();
	MethodMatcher getMethodMatcher();
	Pointcut TRUE = TruePointcut.INSTANCE;
}

Pointcut子类

  • Pointcut

    • AnnotationMatchingPointcut: 主要是匹配对应的class 和method的注解有没有配置的注解。

    • ComposablePointcut: 主要是可以和其他的ClassFilterMethodMatcher,pointcut或者的操作,将它们组合起一个ComposablePointcut操作。

    • ControlFlowPoint: 从调用栈中找对应的method的匹配(匹配的是类名和方法名)。

    • DynamicMethodMatcherPointcut: 继承了DynamicMethodMatcher,其ClassFilter直接为true

      • PerTargetInstantiationModelPointcut: 这个是InstantiationModelAwarePointcutAdvisorImpl 中用的pointcut,主要作用是在aspect实例懒加载时利用preInstantiationPointcut进行实现。先用preThis,pertarget等生命周期中的对应下的切面中配置的对应的表达式进行静态匹配。
    • StaticMethodMatcherPointcut: 继承了StaticMethodMatcher ,对应的ClassFiltertrue,只进行静态匹配对应的目标的method

    • AbstractRegxpMethodPointcut: 维护了匹配正则字符串数组和过滤正则字符串数组。

      • JdkRegxpMethodPointcut: 使用java正则的方式匹配对应的方法名。
    • GetterPointcut: 匹配对应的方法名是否是以get开头的。

    • NameMatchMethodPointcut: 使用*和.来匹配目标方法名。

    • SetterPointcut: 匹配对应的方法名是否是以set开头的。

    • StaticMethodPointcutAdvisor: 匹配静态方法的advisor的抽象类。

  • TruePointcut: calssFilter和MethodMatcher都返回true 。

  • ExpressionPointcut: 提供了一个**getExpression() **方法

  • AbstractExpressionPointcut: 维护了一个字符串的表达式

  • AspectJExpressionPointcut: 利用AspectJ表达式进行匹配。

AspectJExpressionPointcut

AspectJExpressionPointcut是用spring-aop常用的pointcut,在利用@Before,
<aop:advice/>等方式注入advisor时其pointcut都是AspectJExpressionPointcut
所以详细介绍一下这种pointcut。

AspectJExpressionPointcut的是将其对应的表达式转换为PointcutExpression,其对method的匹配结果为ShadowMatch,并利用shadowMatchCache 进行了缓存,而其对应的运行时的匹配则是利用ShadowMatch来进行匹配。

可以看到AspectJExpressionPointcut实现了ClassFilterIntroductionAwareMethodMatcher以及BeanFactoryAware 三个接口,可以看到其对应的MethodMatcherIntroductionAwareMethodMatcher,这个接口,这个接口定义了一个需要参数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中的匹配

ClassFiltermatch方法实现匹配类。可以看到它是用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,targetargs对象进行匹配,而对thistarget对象的获取主要是依赖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

获取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;
	}

pointcut的配置

名称 配置类型 匹配类型
execution 方法表达式 匹配方法执行的连接点
this 类型全限定名 匹配当前的代理对象
target 类型全限定名 匹配目标对象
args 参数类型列表 匹配执行方法传入的参数的类型
within 类型表达式 匹配执行对应类型表达式下的方法
@target 注解类型 匹配目标是否有对应的注解
@within 注解类型 任何目标对象对应的类型是否有对应的注解
@args 注解列表 匹配执行方法传入的参数是否带有指定注解
@annotation 注解类型 匹配当前执行方法持有指定注解的方法
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/cq_pf/article/details/107002566

智能推荐

Docker 快速上手学习入门教程_docker菜鸟教程-程序员宅基地

文章浏览阅读2.5w次,点赞6次,收藏50次。官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。_docker菜鸟教程

电脑技巧:Windows系统原版纯净软件必备的两个网站_msdn我告诉你-程序员宅基地

文章浏览阅读5.7k次,点赞3次,收藏14次。该如何避免的,今天小编给大家推荐两个下载Windows系统官方软件的资源网站,可以杜绝软件捆绑等行为。该站提供了丰富的Windows官方技术资源,比较重要的有MSDN技术资源文档库、官方工具和资源、应用程序、开发人员工具(Visual Studio 、SQLServer等等)、系统镜像、设计人员工具等。总的来说,这两个都是非常优秀的Windows系统镜像资源站,提供了丰富的Windows系统镜像资源,并且保证了资源的纯净和安全性,有需要的朋友可以去了解一下。这个非常实用的资源网站的创建者是国内的一个网友。_msdn我告诉你

vue2封装对话框el-dialog组件_<el-dialog 封装成组件 vue2-程序员宅基地

文章浏览阅读1.2k次。vue2封装对话框el-dialog组件_

MFC 文本框换行_c++ mfc同一框内输入二行怎么换行-程序员宅基地

文章浏览阅读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同一框内输入二行怎么换行

redis-desktop-manager无法连接redis-server的解决方法_redis-server doesn't support auth command or ismis-程序员宅基地

文章浏览阅读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次。济大数电实验报告_数据选择器及其应用

随便推点

灰色预测模型matlab_MATLAB实战|基于灰色预测河南省社会消费品零售总额预测-程序员宅基地

文章浏览阅读236次。1研究内容消费在生产中占据十分重要的地位,是生产的最终目的和动力,是保持省内经济稳定快速发展的核心要素。预测河南省社会消费品零售总额,是进行宏观经济调控和消费体制改变创新的基础,是河南省内人民对美好的全面和谐社会的追求的要求,保持河南省经济稳定和可持续发展具有重要意义。本文建立灰色预测模型,利用MATLAB软件,预测出2019年~2023年河南省社会消费品零售总额预测值分别为21881...._灰色预测模型用什么软件

log4qt-程序员宅基地

文章浏览阅读1.2k次。12.4-在Qt中使用Log4Qt输出Log文件,看这一篇就足够了一、为啥要使用第三方Log库,而不用平台自带的Log库二、Log4j系列库的功能介绍与基本概念三、Log4Qt库的基本介绍四、将Log4qt组装成为一个单独模块五、使用配置文件的方式配置Log4Qt六、使用代码的方式配置Log4Qt七、在Qt工程中引入Log4Qt库模块的方法八、获取示例中的源代码一、为啥要使用第三方Log库,而不用平台自带的Log库首先要说明的是,在平时开发和调试中开发平台自带的“打印输出”已经足够了。但_log4qt

100种思维模型之全局观思维模型-67_计算机中对于全局观的-程序员宅基地

文章浏览阅读786次。全局观思维模型,一个教我们由点到线,由线到面,再由面到体,不断的放大格局去思考问题的思维模型。_计算机中对于全局观的

线程间控制之CountDownLatch和CyclicBarrier使用介绍_countdownluach于cyclicbarrier的用法-程序员宅基地

文章浏览阅读330次。一、CountDownLatch介绍CountDownLatch采用减法计算;是一个同步辅助工具类和CyclicBarrier类功能类似,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。二、CountDownLatch俩种应用场景: 场景一:所有线程在等待开始信号(startSignal.await()),主流程发出开始信号通知,既执行startSignal.countDown()方法后;所有线程才开始执行;每个线程执行完发出做完信号,既执行do..._countdownluach于cyclicbarrier的用法

自动化监控系统Prometheus&Grafana_-自动化监控系统prometheus&grafana实战-程序员宅基地

文章浏览阅读508次。Prometheus 算是一个全能型选手,原生支持容器监控,当然监控传统应用也不是吃干饭的,所以就是容器和非容器他都支持,所有的监控系统都具备这个流程,_-自动化监控系统prometheus&grafana实战

React 组件封装之 Search 搜索_react search-程序员宅基地

文章浏览阅读4.7k次。输入关键字,可以通过键盘的搜索按钮完成搜索功能。_react search