【源码】Spring AOP 7 AspectJAdvisorFactory
前言
此章节介绍 AspectJAdvisorFactory ,这组类主要用于对切面的校验,从切面中解析 Advisor, Advice 等
AspectJAdvisorFactory
public interface AspectJAdvisorFactory {
// 给定class是否切面
boolean isAspect(Class<?> clazz);
// 是否有效切面
void validate(Class<?> aspectClass) throws AopConfigException;
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
@Nullable
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName);
@Nullable
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
}
负责从基于注解的切面解析 Advisor
和 Advice
AbstractAspectJAdvisorFactory
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
// ...
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
// 有 Aspect 注解才行
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
// 至少一个属性前缀为 "ajc$"
private boolean compiledByAjc(Class<?> clazz) {
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().startsWith(AJC_MAGIC)) {
return true;
}
}
return false;
}
// 返回给定方法的第一个 AspectJ 注解
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
// 借助 AnnotationUtils 找给定方法是否有 AspectJ 注解
@Nullable
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
// 找到就封装成 AspectJAnnotation 返回,否则 null
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}
// ...
}
- 抽象基类,主要实现了切面属性的解析、校验等工作
getAdvisors
getAdvisor
getAdvice
方法交给子类实现
ReflectiveAspectJAdvisorFactory
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
// ...
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// AspectJ 实例 -> AspectJ 元数据 -> AspectJ 类
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// AspectJ name
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校验
validate(aspectClass);
// 将 aspectInstanceFactory 包装成 ‘缓存’ MetadataAwareAspectInstanceFactory
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
/**
* 获取类中所有通知方法,在从方法解析Advisor
* Pointcut: AspectJExepressionPointcut
* Advice:AbstractAspectJAdvice
* Advisor:InstantiationModelAwarePointcutAdvisorImpl
*/
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// ...
return advisors;
}
// ...
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 校验
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 此处将切点方法转换成一个 AspectJExpressionPointcut 返回
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 封装成 InstantiationModelAwarePointcutAdvisorImpl 返回
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 获取方法上第一个 AspectJ 注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 这样就将把 AspectJ 切点的匹配全部交由 org.aspectj.weaver 相关类完成
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
// AspectJAnnotation 将方法上 pointcut 或者 value 的值封装到 pointcutExpression
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 从元数据获取类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 校验
validate(candidateAspectClass);
// AspectJ 注解获取
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// ...
AbstractAspectJAdvice springAdvice;
// 根据注解类型实例化成具体的 AbstractAspectJAdvice
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
//...
}
// ...
return springAdvice;
}
// ...
}
AbstractAspectJAdvisorFactory
作为父类完成了 是否切面、切面校验、方法切面注解获取、切面注解封装、切面参数解析 等一些列工作,getAdvisors
getAdvisor
getAdvice
方法交给子类ReflectiveAspectJAdvisorFactory
实现getAdvisors getAdvisor
方法从MetadataAwareAspectInstanceFactory
中获取切面元数据信息,将方法切点解析为对应的AspectJExpressionPointcut
,然后封装成InstantiationModelAwarePointcutAdvisorImpl
返回getAdvice
方法则是基于注解构造对应的AbstractAspectJAdvice
ReflectionUtils.doWithMethods
一个很有意思的反射工具类方法,过滤对应的方法执行指定回调函数(递归调用它父类、接口的方法)
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
Method[] methods = getDeclaredMethods(clazz, false);
for (Method method : methods) {
if (mf != null && !mf.matches(method)) {
continue;
}
try {
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
doWithMethods(clazz.getSuperclass(), mc, mf);
}
else if (clazz.isInterface()) {
for (Class<?> superIfc : clazz.getInterfaces()) {
doWithMethods(superIfc, mc, mf);
}
}
}
InstantiationModelAwarePointcutAdvisorImpl
// 允许延迟加载
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
// Advice 的解析基于 AspectJAdvisorFactory#getAdvice 方法
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
上文提到,AspectJAdvisorFactory
的 getAdvisor
s 方法将切面上的方法解析成对应的 InstantiationModelAwarePointcutAdvisorImpl
,InstantiationModelAwarePointcutAdvisorImpl
作为一个 PointutAdvisor
:
getPointcut
即返回由AspectJAdvisorFactory
解析的AspectJExpressionPointcut
实例getAdvice
则是委托给AspectJAdvisorFactory#getAdvice
方法,返回对应的AbstractAspectJAdvice
实例
可以结合以下 demo
理解
demo
public class AspectJAdvisorFactoryDemo {
@Aspect
public static class MyAspect {
@Pointcut("execution(* *.*())")
public void pointcut() {
}
@Before("pointcut()")
public void before() {
}
}
@Test
public void test() throws NoSuchMethodException {
ReflectiveAspectJAdvisorFactory aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory();
SimpleMetadataAwareAspectInstanceFactory aspectInstanceFactory
= new SimpleMetadataAwareAspectInstanceFactory(MyAspect.class,
"myAspect");
Method m = MyAspect.class.getMethod("before");
// getAdvisors 方法
List<Advisor> advisors = aspectJAdvisorFactory.getAdvisors(aspectInstanceFactory);
// getAdvisor 方法
Advisor advisor = aspectJAdvisorFactory
.getAdvisor(m
, aspectInstanceFactory, 0
, "myAspect");
// 基于 InstantiationModelAwarePointcutAdvisor 获取 Advice
// 实际还是委托 AspectJAdvisorFactory#getAdvice
Advice byAdvisor = null;
Advice byFactory = null;
if (advisor instanceof InstantiationModelAwarePointcutAdvisor) {
InstantiationModelAwarePointcutAdvisor instantiationModelAwarePointcutAdvisor
= (InstantiationModelAwarePointcutAdvisor) advisor;
byAdvisor = instantiationModelAwarePointcutAdvisor.getAdvice();
// 上述方法其实是基于此方法获取
byFactory = aspectJAdvisorFactory.getAdvice(
m
, (AspectJExpressionPointcut) instantiationModelAwarePointcutAdvisor.getPointcut()
, aspectInstanceFactory
, 0, "myAspect"
);
}
}
}
SimpleMetadataAwareAspectInstanceFactory
来实例化切面实例ReflectiveAspectJAdvisorFactory
的getAdvisor
s 方法可以解析上述切面示例中方法对应的Advisor
,这里的实现主要是针对Aspect
封装成对应的InstantiationModelAwarePointcutAdvisorImpl
getAdvice
方法就是解析对应的AbstractAspectJAdvice
类图
序列图
对整个 Advisor
Advice
的解析用序列图做进一步总结
总结
AspectJAdvisorFactory
接口主要就是解析切面实例对应的Advisor
sAdvice
- 实现类
ReflectiveAspectJAdvisorFactory
主要针对AspectJ
切面实例的解析 InstantiationModelAwarePointcutAdvisorImpl = AspectJExpressionPointcut + AbstractAspectJAdvice
上一篇:【源码】Spring AOP 6 AspectInstanceFactory
下一篇:【源码】Spring AOP 8 TargetSource AdvisorAdapter AdvisorAdapterRegistry AdvisorChainFactory