Spring Aop(十)——编程式的Pointcut

不念不忘少年蓝@ 2022-06-07 08:53 375阅读 0赞

编程式的Pointcut

除了可以通过注解和Xml配置定义Pointcut之外,其实我们还可以通过程序来定义Pointcut。Spring Aop的切入点(Pointcut)对应于它的一个Pointcut接口,全称是org.springframework.aop.Pointcut。该接口的定义如下:

  1. public interface Pointcut {
  2. ClassFilter getClassFilter();
  3. MethodMatcher getMethodMatcher();
  4. Pointcut TRUE = TruePointcut.INSTANCE;
  5. }

该接口一共定义了两个核心方法,一个用于获取该Pointcut对应的过滤Class的ClassFilter对象,一个用于获取过滤Method的MethodMatcher对象。
ClassFilter接口的定义如下:

  1. public interface ClassFilter {
  2. boolean matches(Class<?> clazz);
  3. ClassFilter TRUE = TrueClassFilter.INSTANCE;
  4. }

该接口只定义了一个matches方法,用于判断指定的Class对象是否匹配当前的过滤规则。
MethodMatcher接口定义如下:

  1. public interface MethodMatcher {
  2. boolean matches(Method method, Class<?> targetClass);
  3. boolean isRuntime();
  4. boolean matches(Method method, Class<?> targetClass, Object[] args);
  5. MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
  6. }

该接口中一共定义了三个方法,两个matches方法,一个包含方法参数一个不包含。不包含方法参数的matches方法用于判断非运行时的方法匹配,比如只需要匹配方法名、方法参数定义的;包含方法参数值的matches方法用于运行时判断方法是否匹配,应用于需要根据方法传参来判断是否匹配的情况,但是该方法一般会在不包含方法参数的matches方法返回true和isRuntime()方法true的情形下才会调用。isRuntime()方法用于指定该Pointcut是否需要在运行时才能判断对应的方法是否匹配。

自定义Pointcut

以下是一个自定义Pointcut的代码,其将匹配所有的名称Service结尾的Class对应的名称以find开始的方法调用:

  1. import java.lang.reflect.Method;
  2. import org.springframework.aop.ClassFilter;
  3. import org.springframework.aop.MethodMatcher;
  4. import org.springframework.aop.Pointcut;
  5. /** * 自定义Pointcut * @author Elim * 2017年5月8日 */
  6. public class MyCustomPointcut implements Pointcut {
  7. @Override
  8. public ClassFilter getClassFilter() {
  9. return new MyCustomClassFilter();
  10. }
  11. @Override
  12. public MethodMatcher getMethodMatcher() {
  13. return new MyCustomMethodMatcher();
  14. }
  15. private static class MyCustomClassFilter implements ClassFilter {
  16. @Override
  17. public boolean matches(Class<?> clazz) {
  18. //实现自己的判断逻辑,这里简单的判断对应Class的名称是以Service结尾的就表示匹配
  19. return clazz.getName().endsWith("Service");
  20. }
  21. }
  22. private static class MyCustomMethodMatcher implements MethodMatcher {
  23. @Override
  24. public boolean matches(Method method, Class<?> targetClass) {
  25. //实现方法匹配逻辑
  26. return method.getName().startsWith("find");
  27. }
  28. @Override
  29. public boolean isRuntime() {
  30. return false;
  31. }
  32. @Override
  33. public boolean matches(Method method, Class<?> targetClass, Object[] args) {
  34. return false;
  35. }
  36. }
  37. }

然后我们可以定义该自定义Pointcut对应的bean,再定义一个Advisor将使用该Pointcut。如下示例中我们就指定了将在MyCustomPointcut对应的切入点处采用LogAroundAdvice。

  1. <aop:config>
  2. <aop:advisor advice-ref="logAroundAdvice" pointcut-ref="myCustomPointcut"/>
  3. </aop:config>
  4. <bean id="logAroundAdvice" class="com.elim.learn.spring.aop.advice.LogAroundAdvice"/>
  5. <bean id="myCustomPointcut" class="com.elim.learn.spring.aop.pointcut.MyCustomPointcut"/>

继承自现有的Pointcut

除了可以完全实现Pointcut接口外,我们还可以直接使用Spring自带的Pointcut。比如基于固定方法的StaticMethodMatcherPointcut。该Pointcut是一个抽象类,在使用该Pointcut时只需要实现一个抽象方法matches(Method method, Class

  1. public class FindMethodMatcherPointcut extends StaticMethodMatcherPointcut {
  2. @Override
  3. public boolean matches(Method method, Class<?> targetClass) {
  4. return method.getName().startsWith("find");
  5. }
  6. }

关于更多Spring官方已经提供的其它Pointcut定义请参考Spring的API文档。

(注:本文是基于Spring4.1.0所写,Elim写于2017年5月8日)

发表评论

表情:
评论列表 (有 0 条评论,375人围观)

还没有评论,来说两句吧...

相关阅读