切入点源码关系简单图示:
文字阐述如下:
pointcut切入点来源之一:配置的代理接口时,注册代理接口bean的class 为:
package org.springframework.aop;
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
1 、 进入org.springframework.aop.Pointcut ,
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
切入点:实质是规则,即根据类和方法决定在什么地方织入通知。它有两个层面的过滤器:
1) 类层面的过滤器,通过类过滤切面[先在类层面判断能不能加通知,如果不能加,则不会看方法匹层面过滤器,所以类层面的优先级高;]
2)方法层面过滤器,通过方法过滤切面
2 、类层面过滤器:从pointcut进入类过滤器classfilter,classfilter接口决定了一个类是否符合通知的要求,实现该接口的类决定了以参数传递进来的类是否应该被通知,实现该接口的类一般根据类名决定,但不一定必须这样。此外,该接口包含一个内置的实现,是规范的,适用于任何类的classfilter实例,该实现恒成立,适用于只根据方法决定是否符合要求的切入。
public interface ClassFilter {
boolean matches(Class> clazz);
ClassFilter TRUE = TrueClassFilter.INSTANCE;}
3 、方法层面过滤器:进入方法匹配器类MethodMatcher,看到如下源码:
package org.springframework.aop;
import java.lang.reflect.Method;
public interface MethodMatcher {
boolean matches(Method method, Class> targetClass);
boolean isRuntime();
boolean matches(Method method, Class> targetClass, Object[] args);
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}
根据目标的类和方法决定是否应该被通知,因为可以静态的判断,所以可以在aop代理被创建的时候调用一次这个方法,该结果决定通知是否被织入。如果返回TRUE,在代理创建时,运行一次 boolean isRuntime();判断是运行时的吗?即判断该切入点是动态切入点还是静态切入点,是判断参数具体值,来判断通知是否应该被织入(这里知道,动态每次运行都要判断,所以静态性能高)。如果此时返回false,则下面方法永远不会被调用,
boolean matches(Method method, Class> targetClass, Object[] args);
如果返回的是true,则需要根据运行时的参数决定方法是否被通知。
总结:
总结之前先说下切入点,它决定了一个特定类的特定方法是否满足一定的规则。如果符合规则,就将通知应用到该方法上。
静态切入点和动态切入点的区别:
静态切入点特点是通知总是被执行,和方法参数没关系;
动态切入点要根据运行时的参数决定方法是否被通知,这样会增加系统负担,所以尽量避免使用动态切入点。
静态切入点:通知总是执行。
动态切入点:根据运行时参数值的变化。