Spring AOP源码篇一之 PointCut、Advice、Advisor学习

 基本概念:

  • AOP( Aspect-Oriented Programming):直译过来就是面向切面编程。最早是由AOP联盟(AOP Alliance)组织提出来的概念。解决的问题场景:将一些公共代码(日志记录,性能统计,安全控制,事务处理,异常处理等等)抽离出来,系统运行时可动态的应用到业务系统上。
  • 通知(Advice):也称增强,用于实现增强功能的.
  • 连接点(Joinpoint):在匹配目标的哪个位置做增强(before、after、around、return、throw).
  • 切点(Pointcut):用于匹配类或方法,一个切点可以对应多个连接点.
  • 织入 (Weaving):织入是把切面应用到目标对象,一般是通过代理对象实现.

   Spring中另外两个术语:

  •    Advisor:可以理解为是个组件,包含advice和pointcut两个组件
  •    Advised:它是spring AOP代理工厂的配置类接口,负责操作和管理 Advisor 的

Spring AOP与AspectJ:

        AOP是一种概念,Spring AOP和AspectJ都实现了AOP;Spring使用了AspectJ的部分API,生成代理对象Spring用的是JDK动态代理和CGLIB,而AspectJ是通过修改字节码来完成。

        Aspectj可参考另外博文:Java Agent【java探针】及AspectJ-优快云博客

PointCut继承体系:

Pointcut:有两部分组成:ClassFilter 、MethodMatcher;ClassFilter用于过滤Class;MethodMatcher用于匹配方法
package org.springframework.aop

import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;

/**
 * Pointcut由ClassFilter和MethodMatcher构成
 */
public interface Pointcut {

	/**
	 * 返回用于匹配Class的过滤器
	 */
	ClassFilter getClassFilter();

	/**
	 * 返回用于匹配方法的过滤器
	 */
	MethodMatcher getMethodMatcher();


	/**
	 * Pointcut实例: 切点可以匹配适用于所有Class以及方法
	 */
	Pointcut TRUE = TruePointcut.INSTANCE;
}
package org.spring.aop.pointcut;

import org.springframework.aop.IntroductionAdvisor;

/**
 * 切点与目标Class做匹配的过滤器
 *
 * 可以用作{@link Pointcut}的一部分功能,也可以用在引介增强{@link IntroductionAdvisor}匹配目标类
 * 在Spring AOP中主要是为目标类的原有方法增强功能,但是还有一种特殊增强叫引介增强,它不是增强原有的方法而是为原有目标类增加新的方法。
 */
public interface ClassFilter {

	/**
	 * 切点与目标Class进行匹配,判断切点与其是否匹配适用
	 */
	boolean matches(Class<?> clazz);

	/**
	 * ClassFilter实例,切点可以匹配适用于所有目标Class
	 */
	ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
package org.springframework.aop;

import java.lang.reflect.Method;

/**
 * 切点与目标方法做匹配的过滤器
 */
public interface MethodMatcher {

	/**
	 * 静态匹配:只匹配方法对象
	 */
	boolean matches(Method method, Class<?> targetClass);

	/**
	 * 标注动态匹配的,如果返回true,进行动态匹配;返回false,不需要动态匹配
	 */
	boolean isRuntime();

	/**
	 * 动态匹配:匹配方法对象和方法参数对象
	 *  匹配方法:匹配名称、方法注解、方法返回类型、方法返回类型的注解
	 *  匹配参数:匹配参数个数、参数的类型、参数类型的注解
	 */
	boolean matches(Method method, Class<?> targetClass, Object[] args);

	/**
	 * MethodMatcher实例,切点可以匹配适用于所有目标方法
	 */
	MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}
MethodMatcher有个特殊子类IntroductionAwareMethodMatcher,处理<引介增强>这种特殊情况。
<引介增强>与Spring AOP中的普通增强有些不同,普通增强是为目标类的原有方法增强功能,而引介增强是为目标类增加新方法来达到增强的能力
/**
 * MethodMatcher的一种特殊子接口。对方法进行匹配时,将<引介增强>考虑进去,做一些特殊逻辑处理
 */
public interface IntroductionAwareMethodMatcher extends MethodMatcher {
	/**
	 * 与目标方法进行静态匹配时.将<引介增强>因素考虑进去
	 * 
	 * @param hasIntroductions
	 * 		是否有<引介增强>
	 * @return
	 */
	boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);

}

定义一个普通类,用于演示用例
import org.springframework.transaction.annotation.Transactional;

public class UserService {

    @Transactional
    public void say() {
        System.out.println("Hello World!!");
    }
}
自定义类,实现接口Pointcut, ClassFilter, MethodMatcher
import org.springframework.aop.Pointcut;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

public class CustomPointcut implements Pointcut, ClassFilter, MethodMatcher {

    //---------------------------------------------------------------------
    // Implementation of Pointcut
    //---------------------------------------------------------------------
    @Override
    public ClassFilter getClassFilter() {
        return this;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return this;
    }

    //---------------------------------------------------------------------
    // Implementation of ClassFilter
    //---------------------------------------------------------------------
    @Override
    public boolean matches(Class<?> clazz) {
        //判断目标类是否存在注解@Service
        if (clazz.isAnnotationPresent(Service.class)) {
            return true;
        }
        return false;
    }

    //---------------------------------------------------------------------
    // Implementation of MethodMatcher
    //---------------------------------------------------------------------
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        //判断目标方法是否存在注解@Transactional
        if (method.isAnnotationPresent(Transactional.class)) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isRuntime() {
        return false;
    }

    @Override
    public boolean matches(Method method, Class<?> targetClass, Object[] args) {
        throw new UnsupportedOperationException("Illegal MethodMatcher usage");
    }
}
测试代码:
public static void main(String[] args) throws Exception {
        CustomPointcut pointcut = new CustomPointcut();
        boolean matchResult = pointcut.matches(UserService.class);
        System.out.println("ClassFilter.matches(Class<?>)===匹配结果==>" + matchResult);

        Method method = UserService.class.getDeclaredMethod("say", new Class[]{String.class});
        matchResult = pointcut.matches(method, UserService.class);
        System.out.println("MethodMatcher.matches(Method, Class<?>)===匹配结果==>" + matchResult);

        matchResult = pointcut.matches(method, UserService.class, new Class[]{String.class});
        System.out.println("MethodMatcher.matches(Method, Class<?>, args)===匹配结果==>" + matchResult);
    }

执行结果:

Spring2.0开始引入AspectJ,AspectJExpressionPointcut是Spring基于AspectJ表达式而实现的一个Pointcut,AspectJExpressionPointcut在目前spring中使用非常频繁,所以非常重要。
package org.springframework.aop.aspectj;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.patterns.NamePattern;
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
import org.aspectj.weaver.tools.ContextBasedMatcher;
import org.aspectj.weaver.tools.FuzzyBoolean;
import org.aspectj.weaver.tools.JoinPointMatch;
import org.aspectj.weaver.tools.MatchingContext;
import org.aspectj.weaver.tools.PointcutDesignatorHandler;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParameter;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;
import org.aspectj.weaver.tools.ShadowMatch;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.IntroductionAwareMethodMatcher;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.framework.autoproxy.ProxyCreationContext;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
import org.springframework.aop.support.AbstractExpressionPointcut;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * 基于AspectJ表达式功能实现的一个Pointcut子类
 * @since 2.0
 */
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
		implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {

	private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSe
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值