注解切面解析
/**
* 注解切面解析器
*/
public class BeanFactoryAspectJAdvisorsBuilder {
/**
* Bean 工厂
*/
private final ListableBeanFactory beanFactory;
/**
* 生成 Advisor 的工厂
*/
private final AspectJAdvisorFactory advisorFactory;
/**
* 切面 Bean 名称
*/
@Nullable
private volatile List<String> aspectBeanNames;
/**
* 通知者缓存
*/
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
/**
* 切面实例缓存
*/
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
}
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
Assert.notNull(advisorFactory, "AspectJAdvisorFactory must not be null");
this.beanFactory = beanFactory;
this.advisorFactory = advisorFactory;
}
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = aspectBeanNames;
if (aspectNames == null) {
final List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 读取容器中所有的类
final String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
beanFactory, Object.class, true, false);
for (final String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// 读取 Bean 的类型,不能执行初始化操作
final Class<?> beanType = beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 指定的 bean 是否是一个注解切面
if (advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
// 创建切面元数据
final AspectMetadata amd = new AspectMetadata(beanType, beanName);
// 切面是否是单例
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
final MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(beanFactory, beanName);
// 基于目标切面创建相关的 Advisor
final List<Advisor> classAdvisors = advisorFactory.getAdvisors(factory);
// 切面 bean 是单例 && 将通知者加入缓存
if (beanFactory.isSingleton(beanName)) {
advisorsCache.put(beanName, classAdvisors);
}
else {
aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
final MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(beanFactory, beanName);
aspectFactoryCache.put(beanName, factory);
advisors.addAll(advisorFactory.getAdvisors(factory));
}
}
}
aspectBeanNames = aspectNames;
return advisors;
}
}
}
// 无注解切面
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
final List<Advisor> advisors = new ArrayList<>();
for (final String aspectName : aspectNames) {
// 获取指定注解切面的所有 Advisor
final List<Advisor> cachedAdvisors = advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
final MetadataAwareAspectInstanceFactory factory = aspectFactoryCache.get(aspectName);
advisors.addAll(advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
/**
* 指定 bean 名称的切面是否合格
*/
protected boolean isEligibleBean(String beanName) {
return true;
}
}
/**
* 基于标注了 AspectJ 注解的类创建 Spring AOP 通知者
*/
public interface AspectJAdvisorFactory {
/**
* 指定类型是否是一个切面
*/
boolean isAspect(Class<?> clazz);
/**
* 指定类型是否是一个有效的 AspectJ 切面类
*/
void validate(Class<?> aspectClass) throws AopConfigException;
/**
* 将所有标注了 AspectJ 注解的方法转换为 Advisor
*/
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
/**
* 为给定的AspectJ通知方法构建一个Spring AOP通知
*/
@Nullable
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName);
/**
* 为给定的AspectJ通知方法构建一个Spring AOP通知
*
* @param candidateAdviceMethod 候选通知方法
* @param expressionPointcut AspectJ 切点表达式
* @param aspectInstanceFactory Aspect 实例工厂
* @param declarationOrder 通知方法在切面中的声明顺序
* @param aspectName 切面的名称
* @return {@code null} 非通知方法和切点都返回 null
*
* @see org.springframework.aop.aspectj.AspectJAroundAdvice 环绕通知
* @see org.springframework.aop.aspectj.AspectJMethodBeforeAdvice 前置通知
* @see org.springframework.aop.aspectj.AspectJAfterAdvice 后置通知
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice 正常返回通知
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice 异常通知
*/
@Nullable
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
}
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
private static final String AJC_MAGIC = "ajc$";
/**
* AspectJ 注解类型
*/
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
protected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();
/**
* 目标类型是否是一个注解切面【目标类型上存在 @Aspect 注解并且不是由 ajc 编译】
*/
@Override
public boolean isAspect(Class<?> clazz) {
return hasAspectAnnotation(clazz) && !compiledByAjc(clazz);
}
/**
* 目标类型上是否有 Aspect 注解【如果没有直接标注,则尝试递归查找父类及其类型上的注解、实现的接口及其类型上的注解】
*/
private boolean hasAspectAnnotation(Class<?> clazz) {
return AnnotationUtils.findAnnotation(clazz, Aspect.class) != null;
}
private boolean compiledByAjc(Class<?> clazz) {
for (final Field field : clazz.getDeclaredFields()) {
// 方法名称由 ajc$ 开头
if (field.getName().startsWith(AJC_MAGIC)) {
return true;
}
}
return false;
}
@Override
public void validate(Class<?> aspectClass) throws AopConfigException {
// 如果父类有注解而不是抽象类,那就是一个错误
if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
!Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) {
throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
aspectClass.getSuperclass().getName() + "]");
}
final AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
if (!ajType.isAspect()) {
throw new NotAnAtAspectException(aspectClass);
}
if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) {
throw new AopConfigException(aspectClass.getName() + " uses percflow instantiation model: " +
"This is not supported in Spring AOP.");
}
if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) {
throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " +
"This is not supported in Spring AOP.");
}
}
/**
* 查找并返回给定方法上的第一个 AspectJ注释。
* 查找顺序:Pointcut.class, Around.class, Before.class,
* After.class, AfterReturning.class, AfterThrowing.class
*/
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (final Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
final AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
@Nullable
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
final A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}
/**
* AspectJ 注解类型枚举
*/
protected enum AspectJAnnotationType {
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
}
/**
* 对一个 AspectJ 注解进行建模,公开其类型枚举和切点字符串
*/
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap<>(8);
static {
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
}
/**
* 目标注解
*/
private final A annotation;
/**
* AspectJ 注解类型枚举
*/
private final AspectJAnnotationType annotationType;
/**
* 切点字符串
*/
private final String pointcutExpression;
/**
* 参数名称
*/
private final String argumentNames;
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = determineAnnotationType(annotation);
try {
this.pointcutExpression = resolveExpression(annotation);
final Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = argNames instanceof String ? (String) argNames : "";
}
catch (final Exception ex) {
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
}
}
private AspectJAnnotationType determineAnnotationType(A annotation) {
final AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
if (type != null) {
return type;
}
throw new IllegalStateException("Unknown annotation type: " + annotation);
}
private String resolveExpression(A annotation) {
// "pointcut", "value"
for (final String attributeName : EXPRESSION_ATTRIBUTES) {
final Object val = AnnotationUtils.getValue(annotation, attributeName);
if (val instanceof String) {
final String str = (String) val;
if (!str.isEmpty()) {
return str;
}
}
}
throw new IllegalStateException("Failed to resolve expression: " + annotation);
}
public AspectJAnnotationType getAnnotationType() {
return this.annotationType;
}
public A getAnnotation() {
return this.annotation;
}
public String getPointcutExpression() {
return this.pointcutExpression;
}
public String getArgumentNames() {
return this.argumentNames;
}
@Override
public String toString() {
return this.annotation.toString();
}
}
/**
* 解析在 AspectJ 注解级别定义的参数
*/
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
@Override
@Nullable
public String[] getParameterNames(Method method) {
if (method.getParameterCount() == 0) {
return new String[0];
}
// 读取目标方法上的 AspectJ 注解
final AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
if (annotation == null) {
return null;
}
final StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
if (nameTokens.countTokens() > 0) {
final String[] names = new String[nameTokens.countTokens()];
for (int i = 0; i < names.length; i++) {
names[i] = nameTokens.nextToken();
}
return names;
}
else {
return null;
}
}
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
}
}
}
/**
* 通过反射来执行 AspectJ 注解关联的通知方法的 AdvisorFactory
*/
@SuppressWarnings("serial")
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
private static final Comparator<Method> METHOD_COMPARATOR;
static {
final Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
// 根据声明的类型顺序进行排序
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
final AspectJAnnotation<?> annotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return annotation != null ? annotation.getAnnotation() : null;
});
final Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
@Nullable
private final BeanFactory beanFactory;
public ReflectiveAspectJAdvisorFactory() {
this(null);
}
public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 读取切面类型
final Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 读取切面名称
final String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 验证切面类
validate(aspectClass);
// 只实例化切面一次的装饰器
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
final List<Advisor> advisors = new ArrayList<>();
// 读取除切点外的所有方法
for (final Method method : getAdvisorMethods(aspectClass)) {
// 尝试从目标方法上构建 Advisor,创建 InstantiationModelAwarePointcutAdvisorImpl 时即初始化
final Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
final Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 是否需要动态地为指定的类型增加方法:读取当前切面中定义的所有字段
for (final Field field : aspectClass.getDeclaredFields()) {
final Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// 排除切点方法
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
// 排序
methods.sort(METHOD_COMPARATOR);
return methods;
}
/**
* 尝试为指定的类型新增方法
*/
@Nullable
private Advisor getDeclareParentsAdvisor(Field introductionField) {
// 1)目标属性上存在 DeclareParents 注解
final DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
return null;
}
// 2)指定了增强实现
if (DeclareParents.class == declareParents.defaultImpl()) {
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
}
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 读取切点表达式
final AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
/**
* 查找并返回给定方法上的第一个 AspectJ 注释。
* 查找顺序:Pointcut.class, Around.class, Before.class,
* After.class, AfterReturning.class, AfterThrowing.class
*/
final AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 创建 AspectJ 表达式切点
final AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (beanFactory != null) {
ajexp.setBeanFactory(beanFactory);
}
return ajexp;
}
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
final Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
final AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method. Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
// 切点
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
// 环绕通知
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 前置通知
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 后置通知
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 正常返回通知
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
// 如果 AfterReturning 通知将方法返回结果绑定了命名参数
final AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
// 异常通知
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
// 如果 AfterThrowing 通知将方法抛出的异常绑定了命名参数
final AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// 配置 Advice
springAdvice.setAspectName(aspectName);
// 声明顺序
springAdvice.setDeclarationOrder(declarationOrder);
// 解析参数名称
final String[] argNames = parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
// 计算参数绑定
springAdvice.calculateArgumentBindings();
return springAdvice;
}
/**
* 实例化此切面的合成通知则
*/
@SuppressWarnings("serial")
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
(method, args, target) -> aif.getAspectInstance());
}
}
}
/**
* 封装 AspectJ 切面或 AspectJ 注解的通知方法
*/
@SuppressWarnings("serial")
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
/**
* Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.
*/
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
/**
* 延迟初始化当前调用的连接点
*/
public static JoinPoint currentJoinPoint() {
final MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
final ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
if (jp == null) {
jp = new MethodInvocationProceedingJoinPoint(pmi);
pmi.setUserAttribute(JOIN_POINT_KEY, jp);
}
return jp;
}
private final Class<?> declaringClass;
private final String methodName;
private final Class<?>[] parameterTypes;
protected transient Method aspectJAdviceMethod;
private final AspectJExpressionPointcut pointcut;
private final AspectInstanceFactory aspectInstanceFactory;
/**
* 切面 bean 的名称
*/
private String aspectName = "";
/**
* 通知在切面内的声明顺序
*/
private int declarationOrder;
/**
* 通知方法参数名称数组
*/
@Nullable
private String[] argumentNames;
/** 异常通知:目标方法抛出的异常所绑定的参数名称 */
@Nullable
private String throwingName;
/** 正常返回通知:目标方法的执行结果所绑定的参数名称 */
@Nullable
private String returningName;
private Class<?> discoveredReturningType = Object.class;
private Class<?> discoveredThrowingType = Object.class;
/**
* 通知方法的第一个参数为 JoinPoint,则为 0
*/
private int joinPointArgumentIndex = -1;
/**
* 通知方法的第一个参数为 JoinPoint.StaticPart,则为 0
*/
private int joinPointStaticPartArgumentIndex = -1;
@Nullable
private Map<String, Integer> argumentBindings;
/**
* 参数是否已经内省
*/
private boolean argumentsIntrospected = false;
@Nullable
private Type discoveredReturningGenericType;
// Note: Unlike return type, no such generic information is needed for the throwing type,
// since Java doesn't allow exception types to be parameterized.
public AbstractAspectJAdvice(
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
declaringClass = aspectJAdviceMethod.getDeclaringClass();
methodName = aspectJAdviceMethod.getName();
parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.pointcut = pointcut;
this.aspectInstanceFactory = aspectInstanceFactory;
}
public final Method getAspectJAdviceMethod() {
return aspectJAdviceMethod;
}
public final AspectJExpressionPointcut getPointcut() {
calculateArgumentBindings();
return pointcut;
}
/**
* 构建一个排除了 AspectJ 通知方法本身的安全切入点
*/
public final Pointcut buildSafePointcut() {
final Pointcut pc = getPointcut();
final MethodMatcher safeMethodMatcher = MethodMatchers.intersection(
new AdviceExcludingMethodMatcher(aspectJAdviceMethod), pc.getMethodMatcher());
return new ComposablePointcut(pc.getClassFilter(), safeMethodMatcher);
}
public final AspectInstanceFactory getAspectInstanceFactory() {
return aspectInstanceFactory;
}
@Nullable
public final ClassLoader getAspectClassLoader() {
return aspectInstanceFactory.getAspectClassLoader();
}
@Override
public int getOrder() {
return aspectInstanceFactory.getOrder();
}
public void setAspectName(String name) {
aspectName = name;
}
@Override
public String getAspectName() {
return aspectName;
}
public void setDeclarationOrder(int order) {
declarationOrder = order;
}
@Override
public int getDeclarationOrder() {
return declarationOrder;
}
public void setArgumentNames(String argNames) {
final String[] tokens = StringUtils.commaDelimitedListToStringArray(argNames);
setArgumentNamesFromStringArray(tokens);
}
public void setArgumentNamesFromStringArray(String... args) {
argumentNames = new String[args.length];
for (int i = 0; i < args.length; i++) {
argumentNames[i] = StringUtils.trimWhitespace(args[i]);
if (!isVariableName(argumentNames[i])) {
throw new IllegalArgumentException(
"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
argumentNames[i] + "' that is not a valid Java identifier");
}
}
if (argumentNames != null) {
if (aspectJAdviceMethod.getParameterCount() == argumentNames.length + 1) {
// May need to add implicit join point arg name...
final Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
if (firstArgType == JoinPoint.class ||
firstArgType == ProceedingJoinPoint.class ||
firstArgType == JoinPoint.StaticPart.class) {
final String[] oldNames = argumentNames;
argumentNames = new String[oldNames.length + 1];
argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
}
}
}
}
public void setReturningName(String name) {
throw new UnsupportedOperationException("Only afterReturning advice can be used to bind a return value");
}
protected void setReturningNameNoCheck(String name) {
// name could be a variable or a type...
if (isVariableName(name)) {
returningName = name;
}
else {
// assume a type
try {
discoveredReturningType = ClassUtils.forName(name, getAspectClassLoader());
}
catch (final Throwable ex) {
throw new IllegalArgumentException("Returning name '" + name +
"' is neither a valid argument name nor the fully-qualified " +
"name of a Java type on the classpath. Root cause: " + ex);
}
}
}
protected Class<?> getDiscoveredReturningType() {
return discoveredReturningType;
}
@Nullable
protected Type getDiscoveredReturningGenericType() {
return discoveredReturningGenericType;
}
public void setThrowingName(String name) {
throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
}
protected void setThrowingNameNoCheck(String name) {
// name could be a variable or a type...
if (isVariableName(name)) {
throwingName = name;
}
else {
// assume a type
try {
discoveredThrowingType = ClassUtils.forName(name, getAspectClassLoader());
}
catch (final Throwable ex) {
throw new IllegalArgumentException("Throwing name '" + name +
"' is neither a valid argument name nor the fully-qualified " +
"name of a Java type on the classpath. Root cause: " + ex);
}
}
}
protected Class<?> getDiscoveredThrowingType() {
return discoveredThrowingType;
}
private boolean isVariableName(String name) {
final char[] chars = name.toCharArray();
if (!Character.isJavaIdentifierStart(chars[0])) {
return false;
}
for (int i = 1; i < chars.length; i++) {
if (!Character.isJavaIdentifierPart(chars[i])) {
return false;
}
}
return true;
}
/**
* 1)如果第一个参数是 JoinPoint 或 ProceedingJoinPoint,则我们将传递一个 JoinPoint
* 【如果是环绕通知,则传递 ProceedingJoinPoint】给它。
* 2)如果第一个参数是 JoinPoint.StaticPart,则我们将传递一个 JoinPoint.StaticPart 给它。
* 剩余的参数,切点将基于指定的连接点进行计算后执行绑定
*/
public final synchronized void calculateArgumentBindings() {
// 无需执行参数绑定操作
if (argumentsIntrospected || parameterTypes.length == 0) {
return;
}
// 未绑定的参数个数
int numUnboundArgs = parameterTypes.length;
// 通知方法的参数类型数组
final Class<?>[] parameterTypes = aspectJAdviceMethod.getParameterTypes();
/**
* 第一个参数类型是 JoinPoint、ProceedingJoinPoint、JoinPoint.StaticPart,
* 则将 numUnboundArgs 减 1
*/
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
numUnboundArgs--;
}
if (numUnboundArgs > 0) {
// 按照匹配的切入点,返回的名称绑定参数
bindArgumentsByName(numUnboundArgs);
}
argumentsIntrospected = true;
}
/**
* 是否是 JoinPoint
*/
private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
if (JoinPoint.class == candidateParameterType) {
joinPointArgumentIndex = 0;
return true;
}
else {
return false;
}
}
/**
* 是否是 ProceedingJoinPoint
*/
private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
if (ProceedingJoinPoint.class == candidateParameterType) {
if (!supportsProceedingJoinPoint()) {
throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
}
joinPointArgumentIndex = 0;
return true;
}
else {
return false;
}
}
protected boolean supportsProceedingJoinPoint() {
return false;
}
/**
* 是否是 JoinPoint.StaticPart
*/
private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
if (JoinPoint.StaticPart.class == candidateParameterType) {
joinPointStaticPartArgumentIndex = 0;
return true;
}
else {
return false;
}
}
/**
* 根据名称实现参数绑定
*/
private void bindArgumentsByName(int numArgumentsExpectingToBind) {
if (argumentNames == null) {
// 读取参数名称数组
argumentNames = createParameterNameDiscoverer().getParameterNames(aspectJAdviceMethod);
}
if (argumentNames != null) {
// 绑定显示的参数
bindExplicitArguments(numArgumentsExpectingToBind);
}
else {
throw new IllegalStateException("Advice method [" + aspectJAdviceMethod.getName() + "] " +
"requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
"the argument names were not specified and could not be discovered.");
}
}
/**
* 创建一个用于实现参数绑定的 ParameterNameDiscoverer
*/
protected ParameterNameDiscoverer createParameterNameDiscoverer() {
final DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
final AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
new AspectJAdviceParameterNameDiscoverer(pointcut.getExpression());
adviceParameterNameDiscoverer.setReturningName(returningName);
adviceParameterNameDiscoverer.setThrowingName(throwingName);
// Last in chain, so if we're called and we fail, that's bad...
adviceParameterNameDiscoverer.setRaiseExceptions(true);
discoverer.addDiscoverer(adviceParameterNameDiscoverer);
return discoverer;
}
private void bindExplicitArguments(int numArgumentsLeftToBind) {
Assert.state(argumentNames != null, "No argument names available");
argumentBindings = new HashMap<>();
final int numExpectedArgumentNames = aspectJAdviceMethod.getParameterCount();
if (argumentNames.length != numExpectedArgumentNames) {
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
" arguments to bind by name in advice, but actually found " +
argumentNames.length + " arguments.");
}
// 需要显式绑定的参数起始索引
final int argumentIndexOffset = parameterTypes.length - numArgumentsLeftToBind;
for (int i = argumentIndexOffset; i < argumentNames.length; i++) {
argumentBindings.put(argumentNames[i], i);
}
// 如果是 AfterReturning 通知 && 指定了绑定返回值的参数名称
if (returningName != null) {
// 通知方法中不存在此绑定参数,则抛出 IllegalStateException 异常
if (!argumentBindings.containsKey(returningName)) {
throw new IllegalStateException("Returning argument name '" + returningName +
"' was not bound in advice arguments");
}
else {
// 读取参数索引
final Integer index = argumentBindings.get(returningName);
// 写入返回值类型
discoveredReturningType = aspectJAdviceMethod.getParameterTypes()[index];
// 写入返回值泛型
discoveredReturningGenericType = aspectJAdviceMethod.getGenericParameterTypes()[index];
}
}
// 如果是 AfterThrowing 通知 && 指定了绑定异常的参数名称
if (throwingName != null) {
// 通知方法中不存在此绑定参数,则抛出 IllegalStateException 异常
if (!argumentBindings.containsKey(throwingName)) {
throw new IllegalStateException("Throwing argument name '" + throwingName +
"' was not bound in advice arguments");
}
else {
// 读取参数索引
final Integer index = argumentBindings.get(throwingName);
// 写入异常类型
discoveredThrowingType = aspectJAdviceMethod.getParameterTypes()[index];
}
}
// 按需配置切点表达式
configurePointcutParameters(argumentNames, argumentIndexOffset);
}
private void configurePointcutParameters(String[] argumentNames, int argumentIndexOffset) {
int numParametersToRemove = argumentIndexOffset;
if (returningName != null) {
numParametersToRemove++;
}
if (throwingName != null) {
numParametersToRemove++;
}
// 需要执行绑定的切点参数名称数组
final String[] pointcutParameterNames = new String[argumentNames.length - numParametersToRemove];
// 需要执行绑定的切点参数类型数组
final Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
// 通知方法参数类型数组
final Class<?>[] methodParameterTypes = aspectJAdviceMethod.getParameterTypes();
int index = 0;
for (int i = 0; i < argumentNames.length; i++) {
// 尝试跳过第一个参数
if (i < argumentIndexOffset) {
continue;
}
// 尝试跳过 returningName 和 throwingName 参数
if (argumentNames[i].equals(returningName) ||
argumentNames[i].equals(throwingName)) {
continue;
}
pointcutParameterNames[index] = argumentNames[i];
pointcutParameterTypes[index] = methodParameterTypes[i];
index++;
}
// 写入切点参数名称数组
pointcut.setParameterNames(pointcutParameterNames);
// 写入切点参数名称类型数组
pointcut.setParameterTypes(pointcutParameterTypes);
}
/**
* 执行参数绑定并返回绑定后的参数列表
*/
protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable ex) {
calculateArgumentBindings();
// AMC start
final Object[] adviceInvocationArgs = new Object[parameterTypes.length];
int numBound = 0;
if (joinPointArgumentIndex != -1) {
adviceInvocationArgs[joinPointArgumentIndex] = jp;
numBound++;
}
else if (joinPointStaticPartArgumentIndex != -1) {
adviceInvocationArgs[joinPointStaticPartArgumentIndex] = jp.getStaticPart();
numBound++;
}
if (!CollectionUtils.isEmpty(argumentBindings)) {
// binding from pointcut match
if (jpMatch != null) {
final PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
for (final PointcutParameter parameter : parameterBindings) {
final String name = parameter.getName();
final Integer index = argumentBindings.get(name);
adviceInvocationArgs[index] = parameter.getBinding();
numBound++;
}
}
// binding from returning clause
if (returningName != null) {
final Integer index = argumentBindings.get(returningName);
adviceInvocationArgs[index] = returnValue;
numBound++;
}
// binding from thrown exception
if (throwingName != null) {
final Integer index = argumentBindings.get(throwingName);
adviceInvocationArgs[index] = ex;
numBound++;
}
}
if (numBound != parameterTypes.length) {
throw new IllegalStateException("Required to bind " + parameterTypes.length +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
}
return adviceInvocationArgs;
}
/**
* 执行通知方法
*/
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
return aspectJAdviceMethod.invoke(aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (final IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
aspectJAdviceMethod + "]; pointcut expression [" +
pointcut.getPointcutExpression() + "]", ex);
}
catch (final InvocationTargetException ex) {
throw ex.getTargetException();
}
}
protected JoinPoint getJoinPoint() {
return currentJoinPoint();
}
@Nullable
protected JoinPointMatch getJoinPointMatch() {
final MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
return getJoinPointMatch((ProxyMethodInvocation) mi);
}
@Nullable
protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
final String expression = pointcut.getExpression();
return expression != null ? (JoinPointMatch) pmi.getUserAttribute(expression) : null;
}
@Override
public String toString() {
return getClass().getName() + ": advice method [" + aspectJAdviceMethod + "]; " +
"aspect name '" + aspectName + "'";
}
/**
* 排除指定通知方法的 MethodMatcher
* MethodMatcher that excludes the specified advice method.
* @see AbstractAspectJAdvice#buildSafePointcut()
*/
private static class AdviceExcludingMethodMatcher extends StaticMethodMatcher {
private final Method adviceMethod;
public AdviceExcludingMethodMatcher(Method adviceMethod) {
this.adviceMethod = adviceMethod;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return !adviceMethod.equals(method);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AdviceExcludingMethodMatcher)) {
return false;
}
final AdviceExcludingMethodMatcher otherMm = (AdviceExcludingMethodMatcher) other;
return adviceMethod.equals(otherMm.adviceMethod);
}
@Override
public int hashCode() {
return adviceMethod.hashCode();
}
}
}
@SuppressWarnings("serial")
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
public AspectJMethodBeforeAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
@Override
public boolean isBeforeAdvice() {
return true;
}
@Override
public boolean isAfterAdvice() {
return false;
}
}
@SuppressWarnings("serial")
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
public AspectJAroundAdvice(
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJAroundAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return false;
}
@Override
protected boolean supportsProceedingJoinPoint() {
return true;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
final ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
final ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
final JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
/**
* Return the ProceedingJoinPoint for the current invocation,
*/
protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
return new MethodInvocationProceedingJoinPoint(rmi);
}
}
@SuppressWarnings("serial")
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
implements AfterReturningAdvice, AfterAdvice, Serializable {
public AspectJAfterReturningAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
@Override
public void setReturningName(String name) {
setReturningNameNoCheck(name);
}
@Override
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
// 如果返回值类型和关联的通知参数类型匹配,则执行返回通知
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
}
}
private boolean shouldInvokeOnReturnValueOf(Method method, @Nullable Object returnValue) {
final Class<?> type = getDiscoveredReturningType();
final Type genericType = getDiscoveredReturningGenericType();
// If we aren't dealing with a raw type, check if generic parameters are assignable.
return matchesReturnValue(type, method, returnValue) &&
(genericType == null || genericType == type ||
TypeUtils.isAssignable(genericType, method.getGenericReturnType()));
}
/**
* 返回值类型是否匹配
*/
private boolean matchesReturnValue(Class<?> type, Method method, @Nullable Object returnValue) {
if (returnValue != null) {
return ClassUtils.isAssignableValue(type, returnValue);
}
else if (Object.class == type && void.class == method.getReturnType()) {
return true;
}
else {
return ClassUtils.isAssignable(type, method.getReturnType());
}
}
}
@SuppressWarnings("serial")
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 执行目标方法
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
@SuppressWarnings("serial")
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterThrowingAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
@Override
public void setThrowingName(String name) {
setThrowingNameNoCheck(name);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (final Throwable ex) {
// 是否需要执行异常通知
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
/**
* 异常类型是否和通知方法中的参数匹配
*/
private boolean shouldInvokeOnThrowing(Throwable ex) {
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
}
}