您现在的位置是:首页 >其他 >Spring @Pointcut切点详解网站首页其他
Spring @Pointcut切点详解
简介Spring @Pointcut切点详解
pointcut就是切点,通知需要在哪些方法处进行增强,在AspectJ中用@Pointcut
注解表达式标注。
@Pointcut("execution(* com.aop.test.aspect..*.*(..))")
public void pointcut() {}
在spring aop中定义了Pointcut接口规范,其中定义了类过滤器`ClassFilter`和方法匹配器`MethodMatcher`。
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
// 类匹配
public interface ClassFilter {
boolean matches(Class<?> clazz);
}
// 方法匹配
public interface MethodMatcher {
// 方法是否匹配切点(静态匹配)
boolean matches(Method method, Class<?> targetClass);
// 代理对象已经创建,静态匹配成功(两个参数的matches)
// 方法调用时检查三个参数的matches方法是否匹配
boolean isRuntime();
// 动态匹配,方法调用时带参数判断
boolean matches(Method method, Class<?> targetClass, Object... args);
}
针对与AspectJ的实现
相关类结构:
抽象类主要定义了切点表达式expression
public abstract class AbstractExpressionPointcut implements ExpressionPointcut, Serializable {
@Nullable
private String location;
@Nullable
private String expression;
}
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
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);
}
@Nullable
private Class<?> pointcutDeclarationScope;
private String[] pointcutParameterNames = new String[0];
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
@Nullable
private BeanFactory beanFactory;
@Nullable
private transient ClassLoader pointcutClassLoader;
@Nullable
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);
}
AspectJExpressionPointcut的具体实现有兴趣在慢慢分析,其最主要的意图就是解析@Pointcut
注解表达式,调用ClassFilter#matches(Class)
和MethodMatcher#matches(Method, Class)
判断目标类及方法是否符合切点表达式的定义。
Spring事务如何实现的Pointcut
Spring事务也是通过AOP的方式来实现,那么事务必然也需要有其对应的切点匹配方式,这里我们讨论注解申明式事务@Transaction
,不难猜测这里的切点匹配就是判断目标类(及其方法)上是否有标记@Transaction
注解,类上或类中任意一个方法上标记了@Transaction
那么这个类就需要被代理,在方法调用时在具体判断方法是否需要事务。
public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {
// 定义类过滤字段
private ClassFilter classFilter = ClassFilter.TRUE;
}
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
// 方法是否匹配
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
// 获取事务属性,交给子类实现
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
// 内部类实现的类过滤器
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
// 基础设施类忽略
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 调用子类实现的获取事务属性
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
在事务实现的Advisor中实现了具体的实现类
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
// 匿名内部类实现
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return BeanFactoryTransactionAttributeSourceAdvisor.this.transactionAttributeSource;
}
};
}
这里可以看出在IOC容器中BeanFactoryTransactionAttributeSourceAdvisor
的bean中设置的TransactionAttributeSource
就是获取事务属性的具体工具类,详细的分析我们在事务中再细细道来,参见事务桥接AOP,TransactionAttributeSource。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。