切点表达式
代码地址:WangChao-ly/chao-spring at pointcut-expression (github.com)
建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!
Joinpoint,织入点,指需要执行代理操作的某个类的某个方法(仅支持方法级别的JoinPoint);Pointcut是JoinPoint的表述方式,能捕获JoinPoint。
最常用的切点表达式是AspectJ的切点表达式。需要匹配类,定义ClassFilter接口;匹配方法,定义MethodMatcher接口。PointCut需要同时匹配类和方法,包含ClassFilter和MethodMatcher,AspectJExpressionPointcut是支持AspectJ切点表达式的PointCut实现,简单实现仅支持execution函数。
- ClassFilter:匹配类的接口
public interface ClassFilter {
/**
* 匹配类
* @param clazz
* @return
*/
boolean matches(Class<?> clazz);
}
- MethodMatcher:匹配方法的接口
public interface MethodMatcher {
/**
* 方法匹配
* @param method
* @param targetClass
* @return
*/
boolean matches(Method method, Class<?> targetClass);
}
- PintCut:该接口是继承上面两个接口,既能匹配类,又能匹配方法
- AspectJExpressionPointcut:该接口是PointCut的实现类,通过aspectj包的方法,解析用户指定范围的类和方法进行匹配
public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {
/**
* 切面编程中支持的不同切点类型的枚举值或常量
*/
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
static{
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
}
private final PointcutExpression pointcutExpression;
public AspectJExpressionPointcut(String expression){
//拿到pointcutParser
PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES,this.getClass().getClassLoader());
pointcutExpression = pointcutParser.parsePointcutExpression(expression);
}
@Override
public boolean matches(Class<?> clazz) {
return pointcutExpression.couldMatchJoinPointsInType(clazz);
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return pointcutExpression.matchesMethodExecution(method).alwaysMatches();
}
@Override
public ClassFilter getClassFilter() {
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
return this;
}
}
- 测试
public class PointcutExpressionTest {
@Test
public void testPointcutExpression() throws Exception {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut("execution(* org.springframework.test.service.HelloService.*(..))");
Class<HelloService> clazz = HelloService.class;
Method method = clazz.getDeclaredMethod("sayHello");
//匹配类和方法
Assert.isTrue(pointcut.matches(clazz));
Assert.isTrue(pointcut.matches(method, clazz));
}
}