前言
复制下哉ZY-》 : https://www.97yrbl.com/t-1389.html
AOP是我们使用Spring时较为常用的功能,今天让我们来看看其中的玄机
@EnableAspectJAutoProxy
项目中使用AOP的时候,都必须在某个类上标注@EnableAspectJAutoProxy,代表开启AOP,这个开启AOP是什么意思呢?
@Aspect
@Component
@Slf4j
@EnableAspectJAutoProxy
public class AspectTest {
}
复制代码
点击进去EnableAspectJAutoProxy,会发现EnableAspectJAutoProxy import 了AspectJAutoProxyRegistrar类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
复制代码
在之前的Spring文章中,我曾写过,@Import这个注解可以引入三种类型的类
- ImportSelector类型
- ImportBeanDefinitionRegistrar类型
- 普通类
不管哪种类型,都是注册BeanDefinition的一种方式,此处Import的是ImportBeanDefinitionRegistrar,这个类注册了AnnotationAwareAspectJAutoProxyCreator这个BeanDefinition
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
复制代码
看看AnnotationAwareAspectJAutoProxyCreator这个类的继承图,会发现它只是在原有Spring-AOP的基础上做了注解方面的扩展。需要特别注意的是,该类实现了BeanPostProcessor,对Spring源码比较熟悉的同学应该知道实现这个类意味着什么,说明AOP是在Spring原有Bean生命周期上加东西,并没有逃脱Spring的牢笼
一些基础知识
Advice与Advisor
我们经常会看到Advice、Advisor,他们有什么区别呢?
Advice是通知,Advisor是增强器,每个Advisor都会持有一个Advice
public interface Advisor {
Advice EMPTY_ADVICE = new Advice() {};
// 比如这个接口,可以获取Advisor持有的Advice
Advice getAdvice();
boolean isPerInstance();
}
复制代码
AopInfrastructureBean
// Spring内部的这个接口没有任何实现,只是一个标记接口,如果Spring中的类实现了这个接口,就会被标记为Spring的基础设施类
// 不会被自动代理
public interface AopInfrastructureBean {
}
// 在AbstractAutoProxyCreator这个类中,有一个方法,判断某个类需不需要被代理
// 如果是Advice、Pointcut、Advisor、AopInfrastructureBean的子类,则不需要被代理
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
复制代码
Pointcut
Pointcut作为Spring AOP最顶级的抽象,主要负责对系统相应Joinpoint的捕获,如果把Joinpoint比做数据,那么Pointcut就是查询条件,一个Pointcut可以对应多个Joinpoint。ClassFilter和MethodMatcher分别限定在不同级别上对于Joinpoint的匹配,ClassFilter是类级别,MethodMatcher是方法级别,使用AOP的同学应该都清楚,AOP主要支持方法级别的匹配,所以类级别的匹配功能较为简单
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
public interface ClassFilter {
// 给定的类是否匹配
boolean matches(Class<?> clazz);
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
public interface MethodMatcher {
// 在这里有一个静态切入点和动态切入点的概念
// 静态切入点:只进行一次检测
// 动态切入点:每次切入都检测
boolean matches(Method method, Class<?> targetClass);
// 判断静态切入点和动态切入点的标志,return true表示动态
boolean isRuntime();
boolean matches(Method method, Class<?> targetClass, Object... args);
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}
复制代码
IntroductionAdvisor
为AOP提供类级别的拦截
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
ClassFilter getClassFilter();
void validateInterfaces() throws IllegalArgumentException;
}
public interface IntroductionInfo {
// 这个接口可以定义AOP适用的类,不适用的类,可以不进行AOP拦截
Class<?>[] getInterfaces();
}
复制代码
PointcutAdvisor
为AOP提供方法级别的拦截
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
复制代码
单纯看以上几个类,可能会很懵,下面是AOP过程中获取拦截器链的代码,结合这些代码感受一下AOP是如何对Advisor进行筛选的
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// 如果advisor是PointcutAdvisor的实例
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 如果是预先筛选过或者advisor适用于目标类
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 进行方法级别的筛选
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 如果是动态切入点
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 如果advisor是IntroductionAdvisor的实例
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
// 以上两种都不是
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}