一、前言
AOP(Aspect Oriented Programming)称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。
AOP的相关概念:
(1)横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
(2)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(3)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用。被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
(4)Advice(通知):AOP在特定的切入点上执行的增强处理,有before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕)
(5)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(6)weave(织入):将切面应用到目标对象并导致代理对象创建的过程
(7)introduction(引入):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
(8)AOP代理(AOP Proxy):AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
(9)目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO
二、源码解析
下面针对Spring Boot的AOP使用进行源码解析。Spring Boot 添加pom引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
之后我们创建切面类
@Aspect
@Component
@EnableAspectJAutoProxy
public class ServiceAdvice {
@Pointcut("@annotation(aoptest.Monitor)")
public void annotation() {
}
@Pointcut("execution(public * aoptest.*.*(..))")
public void webLog(){}
@Before("webLog()")
public void beforeMethodAdviceA(JoinPoint joinPoint){
System.out.println("beforeMethodAdviceA");
}
@Before("annotation()")
public void beforeMethodAdviceAnnotation(JoinPoint joinPoint){
System.out.println("AdviceAnnotation");
}
@Before("annotation()")
public void beforeMethodAdviceAnnotation2(JoinPoint joinPoint){
System.out.println("AdviceAnnotation2");
}
@After("webLog()")
public void afterMethodAdviceB(JoinPoint joinPoint){
System.out.println("afterMethodAdviceB");
}
}
这样就会在对应的方法执行前,进行增强处理了。
首先进入@EnableAspectJAutoProxy注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//导入了AspectJAutoProxyRegistrar
}
导入了AspectJAutoProxyRegistrar类。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
.........................
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
通过AspectJAutoProxyRegistrar类导入了AnnotationAwareAspectJAutoProxyCreator对象。AnnotationAwareAspectJAutoProxyCreator对象实现了BeanPostProcessor接口。
在创建Bean对象的时候会执行AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization方法。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
getAdvicesAndAdvisorsForBean方法用于查找增强的方法和该Bean是否需要AOP处理。
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//找到增强集合
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到实现了Advisor接口的类和标有@Aspect注解的类
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//判断当前的Bean是否有方法适配AOP
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
// 找到所有实现Advisor接口的类
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
//找到所有标有@Aspect的类
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
.......................
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
...............
if (this.advisorFactory.isAspect(beanType)) {
...........................
//此方法将@Aspect类中的包含Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的增强方法找到
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
...........
}
}
//判断当前的Bean是否有方法适配AOP
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//判断是否适配
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
//判断当前类是否有方法适配当前adviors
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
canApply方法中,pc.getClassFilter().matches(targetClass)方法会进行一次快速匹配(只看类是否匹配)。会调用PointcutExpressionImpl类的couldMatchJoinPointsInType方法。
public boolean couldMatchJoinPointsInType(Class aClass) {
ResolvedType matchType = world.resolve(aClass.getName());
if (matchType.isMissing() && (world instanceof ReflectionWorld)) {
// Class is a generated class that cannot be 'looked up' via getResource.
// For example a proxy or lambda.
// Use the class itself in this case
matchType = ((ReflectionWorld)world).resolveUsingClass(aClass);
}
ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world);
boolean couldMatch = pointcut.fastMatch(info).maybeTrue();
if (MATCH_INFO) {
System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': "
+ couldMatch);
}
return couldMatch;
}
通过具体的pointcut调用fastMatch方法。例如AnnotationPointcut会判断方法是否有对应注解,通常采用最多的execution表达式的则会进入KindedPointcut的fastMatch方法。
方法会先对@Pointcut进行解析,看是适配接口还是适配为实体类。判断Bean对象是否适配,表达式如果不适配,有两种情况:
1、如果切点为实体类,则先判断Bean类是否与切点类相同,如不同,则会看父类是否适配。
2、如果切点为接口,则先判断Bean类是否与切点类相同,如不同,则看接口类是否为切面适配的类。
也就是说,如果一个子类A,父类SuperA,如果切点定义的是父类A @Pointcut("execution(public * aoptest.SuperA.*(..))"),这时切点调用的是子类A的任意方法,那么也会进行AOP增强。
进入匹配方法
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
if (shadowMatch.alwaysMatches()) {
return true;
}
else if (shadowMatch.neverMatches()) {
return false;
}
else {
// the maybe case
if (hasIntroductions) {
return true;
}
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
}
}
obtainPointcutExpression方法用于获取切点对应的解析类。
private PointcutExpression obtainPointcutExpression() {
if (getExpression() == null) {
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
if (this.pointcutExpression == null) {
this.pointcutClassLoader = determinePointcutClassLoader();
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
}
return this.pointcutExpression;
}
private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
PointcutParser parser = initializePointcutParser(classLoader);
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = parser.createPointcutParameter(
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),
this.pointcutDeclarationScope, pointcutParameters);
}
initializePointcutParser初始化切点类解析对象
private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
PointcutParser parser = PointcutParser
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
SUPPORTED_PRIMITIVES, classLoader);
parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
return parser;
}
//其中SUPPORTED_PRIMITIVES包含各种pointcut类型,如EXECUTION、annotation等
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
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);
}
parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()), this.pointcutDeclarationScope, pointcutParameters)用于创建当前adviors对应的PointCut解析类。
public PointcutExpression parsePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters)
throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
PointcutExpressionImpl pcExpr = null;
try {
//解析切点表达式,用于创建对应的PointCut解析类
Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters);
pc = concretizePointcutExpression(pc, inScope, formalParameters);
validateAgainstSupportedPrimitives(pc, expression); // again, because we have now followed any ref'd pcuts
pcExpr = new PointcutExpressionImpl(pc, expression, formalParameters, getWorld());
} catch (ParserException pEx) {
throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
} catch (ReflectionWorld.ReflectionWorldException rwEx) {
throw new IllegalArgumentException(rwEx.getMessage());
}
return pcExpr;
}
protected Pointcut resolvePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters) {
try {
PatternParser parser = new PatternParser(expression);
parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
//创建PointCut实现类
Pointcut pc = parser.parsePointcut(); // more correctly: parsePointcut(true)
validateAgainstSupportedPrimitives(pc, expression);
IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
pc = pc.resolve(resolutionScope);
return pc;
} catch (ParserException pEx) {
throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
}
}
通过parser.parsePointcut()创建PointCut实现类
public Pointcut parsePointcut() {
Pointcut p = parseAtomicPointcut();
if (maybeEat("&&")) {
p = new AndPointcut(p, parseNotOrPointcut());
}
if (maybeEat("||")) {
p = new OrPointcut(p, parsePointcut());
}
return p;
}
private Pointcut parseAtomicPointcut() {
if (maybeEat("!")) {
int startPos = tokenSource.peek(-1).getStart();
Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
return p;
}
if (maybeEat("(")) {
Pointcut p = parsePointcut();
eat(")");
return p;
}
//如果Adviors的表达式是@开头,则创建AnnotationPointcut类
if (maybeEat("@")) {
int startPos = tokenSource.peek().getStart();
Pointcut p = parseAnnotationPointcut();
int endPos = tokenSource.peek(-1).getEnd();
p.setLocation(sourceContext, startPos, endPos);
return p;
}
int startPos = tokenSource.peek().getStart();
//之前实例类创建的是 @Before("annotation()") 和 @Before("webLog()")会进入parseSinglePointcut方法寻找
Pointcut p = parseSinglePointcut();
int endPos = tokenSource.peek(-1).getEnd();
p.setLocation(sourceContext, startPos, endPos);
return p;
}
public Pointcut parseSinglePointcut() {
int start = tokenSource.getIndex();
IToken t = tokenSource.peek();
Pointcut p = t.maybeGetParsedPointcut();
if (p != null) {
tokenSource.next();
return p;
}
String kind = parseIdentifier();
//这里也没有适配的,我们传入的是annotation() 和 webLog()
if (kind.equals("execution") || kind.equals("call") || kind.equals("get") || kind.equals("set")) {
p = parseKindedPointcut(kind);
} else if (kind.equals("args")) {
p = parseArgsPointcut();
} else if (kind.equals("this")) {
p = parseThisOrTargetPointcut(kind);
} else if (kind.equals("target")) {
p = parseThisOrTargetPointcut(kind);
} else if (kind.equals("within")) {
p = parseWithinPointcut();
} else if (kind.equals("withincode")) {
p = parseWithinCodePointcut();
} else if (kind.equals("cflow")) {
p = parseCflowPointcut(false);
} else if (kind.equals("cflowbelow")) {
p = parseCflowPointcut(true);
} else if (kind.equals("adviceexecution")) {
eat("(");
eat(")");
p = new KindedPointcut(Shadow.AdviceExecution, new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY,
AnnotationTypePattern.ANY));
} else if (kind.equals("handler")) {
eat("(");
TypePattern typePat = parseTypePattern(false, false);
eat(")");
p = new HandlerPointcut(typePat);
} else if (kind.equals("lock") || kind.equals("unlock")) {
p = parseMonitorPointcut(kind);
} else if (kind.equals("initialization")) {
eat("(");
SignaturePattern sig = parseConstructorSignaturePattern();
eat(")");
p = new KindedPointcut(Shadow.Initialization, sig);
} else if (kind.equals("staticinitialization")) {
eat("(");
TypePattern typePat = parseTypePattern(false, false);
eat(")");
p = new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION,
ModifiersPattern.ANY, TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, ThrowsPattern.ANY,
AnnotationTypePattern.ANY));
} else if (kind.equals("preinitialization")) {
eat("(");
SignaturePattern sig = parseConstructorSignaturePattern();
eat(")");
p = new KindedPointcut(Shadow.PreInitialization, sig);
} else if (kind.equals("if")) {
// - annotation style only allows if(), if(true) or if(false)
// - if() means the body of the annotated method represents the if expression
// - anything else is an error because code cannot be put into the if()
// - code style will already have been processed and the call to maybeGetParsedPointcut()
// at the top of this method will have succeeded.
eat("(");
if (maybeEatIdentifier("true")) {
eat(")");
p = new IfPointcut.IfTruePointcut();
} else if (maybeEatIdentifier("false")) {
eat(")");
p = new IfPointcut.IfFalsePointcut();
} else {
if (!maybeEat(")")) {
throw new ParserException(
"in annotation style, if(...) pointcuts cannot contain code. Use if() and put the code in the annotated method",
t);
}
// TODO - Alex has some token stuff going on here to get a readable name in place of ""...
p = new IfPointcut("");
}
} else {
boolean matchedByExtensionDesignator = false;
// see if a registered handler wants to parse it, otherwise
// treat as a reference pointcut
for (PointcutDesignatorHandler pcd : pointcutDesignatorHandlers) {
if (pcd.getDesignatorName().equals(kind)) {
p = parseDesignatorPointcut(pcd);
matchedByExtensionDesignator = true;
}
}
if (!matchedByExtensionDesignator) {
tokenSource.setIndex(start);
//annotation() 和 webLog() 会进入这里
p = parseReferencePointcut();
}
}
return p;
}
由于我们的Adviors创建的都是@Before("webLog()")和@Before("annotation()"),所以会走到最后parseReferencePointcut创建引用类型的PointCut。
继续回到之前的resolvePointcutExpression方法
protected Pointcut resolvePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters) {
try {
PatternParser parser = new PatternParser(expression);
parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
//创建完ReferencePointcut类后
Pointcut pc = parser.parsePointcut(); // more correctly: parsePointcut(true)
validateAgainstSupportedPrimitives(pc, expression);
IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
//这里会解析ReferencePointcut这正的对应@PointCut的方法,找到真正的Pointcut解析类
pc = pc.resolve(resolutionScope);
return pc;
} catch (ParserException pEx) {
throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
}
}
这里会解析ReferencePointcut这正的对应@PointCut的方法,找到真正的Pointcut解析类。
public final Pointcut resolve(IScope scope) {
assertState(SYMBOLIC);
Bindings bindingTable = new Bindings(scope.getFormalCount());
IScope bindingResolutionScope = scope;
if (typeVariablesInScope.length > 0) {
bindingResolutionScope = new ScopeWithTypeVariables(typeVariablesInScope, scope);
}
//根据引用切点方法名称,找到对应的point里真正的要创建的PointCut
this.resolveBindings(bindingResolutionScope, bindingTable);
bindingTable.checkAllBound(bindingResolutionScope);
this.state = RESOLVED;
return this;
}
public void resolveBindings(IScope scope, Bindings bindings) {
//找到对应名字的pointCut
ResolvedPointcutDefinition pointcutDef = searchType.findPointcut(name);
............
}
public ResolvedPointcutDefinition findPointcut(String name) {
for (Iterator<ResolvedMember> i = getPointcuts(); i.hasNext();) {
ResolvedPointcutDefinition f = (ResolvedPointcutDefinition) i.next();
// the ResolvedPointcutDefinition can be null if there are other problems that prevented its resolution
if (f != null && name.equals(f.getName())) {
return f;
}
}
}
//getPointcuts()方法会调用PointcutGetter.get 方法,会调用getDeclaredPointcuts()
private static class PointcutGetter implements Iterators.Getter<ResolvedType, ResolvedMember> {
@Override
public Iterator<ResolvedMember> get(ResolvedType o) {
return Iterators.array(o.getDeclaredPointcuts());
}
}
会调用Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts方法。
public ResolvedMember[] getDeclaredPointcuts() {
if (pointcuts == null) {
Pointcut[] pcs = this.myType.getDeclaredPointcuts();
......
}
for (int i = 0; i < pcs.length; i++) {
String pcExpr = pcs[i].getPointcutExpression().toString();
org.aspectj.weaver.patterns.Pointcut pc = parser.resolvePointcutExpression(pcExpr, getBaseClass(), parameters[i]);
((ResolvedPointcutDefinition) pointcuts[i]).setParameterNames(pnames);
((ResolvedPointcutDefinition) pointcuts[i]).setPointcut(pc);
}
}
public Pointcut[] getDeclaredPointcuts() {
if (declaredPointcuts != null) return declaredPointcuts;
List<Pointcut> pointcuts = new ArrayList<Pointcut>();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Pointcut pc = asPointcut(method);
if (pc != null) pointcuts.add(pc);
}
Pointcut[] ret = new Pointcut[pointcuts.size()];
pointcuts.toArray(ret);
declaredPointcuts = ret;
return ret;
}
private Pointcut asPointcut(Method method) {
org.aspectj.lang.annotation.Pointcut pcAnn = method.getAnnotation(org.aspectj.lang.annotation.Pointcut.class);
if (pcAnn != null) {
String name = method.getName();
if (name.startsWith(ajcMagic)) {
// extract real name
int nameStart = name.indexOf("$$");
name = name.substring(nameStart +2,name.length());
int nextDollar = name.indexOf("$");
if (nextDollar != -1) name = name.substring(0,nextDollar);
}
return new PointcutImpl(name,pcAnn.value(),method,AjTypeSystem.getAjType(method.getDeclaringClass()),pcAnn.argNames());
} else {
return null;
}
}
通过Java15ReflectionBasedReferenceTypeDelegate找到Adviors方法所对应的Aspect类中有@Pointcut注解的方法。之后对这些方法再次执行parser.resolvePointcutExpression(pcExpr, getBaseClass(), parameters[i]),进行解析。创建这正对应的PointCut类。
继续回到匹配方法
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
if (shadowMatch.alwaysMatches()) {
return true;
}
else if (shadowMatch.neverMatches()) {
return false;
}
else {
// the maybe case
if (hasIntroductions) {
return true;
}
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
}
}
执行getTargetShadowMatch方法。该方法的作用主要是用来判断该Bean是否有方法匹配这些Adviors。
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
..............
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
}
}
public ShadowMatch matchesMethodExecution(Method aMethod) {
ShadowMatch match = matchesExecution(aMethod);
if (MATCH_INFO && match.maybeMatches()) {
System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
+ (match.alwaysMatches() ? "YES" : "MAYBE"));
}
return match;
}
private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
//之前创建的对应PointCut进行匹配判断
org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
Test residueTest = Literal.TRUE;
ExposedState state = getExposedState();
if (match.maybeTrue()) {
residueTest = pointcut.findResidue(forShadow, state);
}
ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters);
sm.setMatchingContext(this.matchContext);
return sm;
}
进入匹配方法matchInternal
public final FuzzyBoolean match(Shadow shadow) {
if (shadow.shadowId == lastMatchedShadowId) {
return lastMatchedShadowResult;
}
FuzzyBoolean ret;
// this next test will prevent a lot of un-needed matching going on....
if (shadow.getKind().isSet(couldMatchKinds())) {
ret = matchInternal(shadow);
} else {
ret = FuzzyBoolean.NO;
}
lastMatchedShadowId = shadow.shadowId;
lastMatchedShadowResult = ret;
return ret;
}
这里以@annotation注解为例,其余的类似。
protected FuzzyBoolean matchInternal(Shadow shadow) {
AnnotatedElement toMatchAgainst = null;
Member member = shadow.getSignature();
ResolvedMember rMember = member.resolve(shadow.getIWorld());
...................
annotationTypePattern.resolve(shadow.getIWorld());
return annotationTypePattern.matches(toMatchAgainst);
}
public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {
if (!isForParameterAnnotationMatch()) {
boolean checkSupers = false;
if (getResolvedAnnotationType().isInheritedAnnotation()) {
if (annotated instanceof ResolvedType) {
checkSupers = true;
}
}
if (annotated.hasAnnotation(annotationType)) {
if (annotationType instanceof ReferenceType) {
ReferenceType rt = (ReferenceType) annotationType;
if (rt.getRetentionPolicy() != null && rt.getRetentionPolicy().equals("SOURCE")) {
rt.getWorld()
.getMessageHandler()
.handleMessage(
MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,
annotationType, annotated), getSourceLocation()));
return FuzzyBoolean.NO;
}
}
................
}
会调用ExactAnnotationTypePattern.matches方法,就是判断注解和方法上的注解是否一致,如果一样,则该方法需要进行AOP增强。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
由canApply可知,如果一个Bean中的任何一个方法满足了Advoirs,那么直接返回true。这是因为即使有一个方法匹配成功,该类也需要创建动态代理,所以该Bean中的其他方法暂时就没必要在循环判断了。
在postProcessAfterInitialization方法中
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
通过createProxy创建的动态代理,会再次判断具体方法是否适配Adviors,并放到缓存中。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
创建的代理主要有JdkDynamicAopProxy和CglibAopProxy两种,以JdkDynamicAopProxy的invoke方法为例。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
..........................
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
..........................
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
因为之前校验的是如果该类中有任一方法符合@Apsect,则直接创建动态代理。这里判断的是具体调用方法是否需要进行增强。并把需要增加AOP的增强和对应方法,放入缓存中。
以上就是AOP匹配源码解析。
AOP匹配源码解析总结:
1、通过@EnableAspectJAutoProxy注解,导入AnnotationAwareAspectJAutoProxyCreator类,AnnotationAwareAspectJAutoProxyCreator类实现了BeanPostProcessor接口。在postProcessAfterInitialization方法中,查找包含@Apsect和实现Adviors接口的类。查找所有包含@Around,@Before,@After,@AfterReturning,@AfterThrowing的增强方法。
2、通过AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply方法进行匹配。匹配步骤如下:
1)进入AspectJExpressionPointcut.matches方法进行匹配。调用AspectJExpressionPointcut.buildPointcutExpression方法创建解析表达式。首先针对@Aound,@Before,@After等引用的pointcut方法名解析,如@Before("webLog()")和@Before("annotation()")等,都会首先创建一个ReferencePointcut类。
2)之后调用ReferencePointcut.resolveBindings方法,找到这些引用名字为webLog()和annotation()的@PointCut方法。并通过最终调用Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts方法,将找到的@PointCut进行再次解析,获得真正的Pointcut解析类。
3)之前创建的ReferencePointcut会再次调用concretize1方法,找到真正的Pointcut解析类。之后进行匹配。
3、如果一个Bean中的任何一个方法满足了Advoirs,那么直接返回true。这是因为即使有一个方法匹配成功,该类也需要创建动态代理。
4、最后通过动态代理判断具体的调用方法是否需要进行增强。并把需要增加AOP的增强和对应方法,放入缓存中