赞
踩
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匹配源码解析。
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的增强和对应方法,放入缓存中
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。