获取增强器细节补充
先介绍下几个核心类
接口傻吊 | 功能 | 说明 |
---|
AspectJAdvisorFactory | 用来创建增强方法的工厂 | 一般实现类是:ReflectiveAspectJAdvisorFactory | AspectJExpressionPointcut | 封装了切入点 | 即@PointCut注解的信息 | InstantiationModelAwarePointcutAdvisorImpl | 封装了增强器信息 | 封装思想 | Advice | 增强器 | 增强器是有多种类型的,关于增强器的介绍见下表 |
再介绍不同类型的增强器(Advice):
类型 | 功能 | 说明 |
---|
AspectJAroundAdvice | 环绕增强 | 对应@Around 注解 | AspectJMethodBeforeAdvice | 前置增强 | 对应@Before 注解 | AspectJAfterAdvice | 后置增强(要求无异常) | 对应@After 注解 | AspectJAfterReturningAdvice | 返回增强 | 对应@AfterReturning 注解 | AspectJAfterThrowingAdvice | 异常增强 | 对应@AfterThrowing 注解 |
说明上文为何在源码没有看到@Before注解等
@Before 注解的解析必然在处理候选增强器的某个步骤遗漏了。 重看查找候选增强器的方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
查看findCandidateAdvisors的实现发现有2个,但是我们是从AnnotationAwareAspectJAutoProxyCreator调用过来的, 所以这里是调用的子类的findCandidateAdvisors方法。继续看子类的findCandidateAdvisors方法。
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
在该方法中,先调用父类的findCandidateAdvisors得到一批候选增强器,其实就是通过实现Advisor 接口来增强的方法(上文已经分析了); 而在buildAspectJAdvisors也得到一批增强器,其实就是通过@AspectJ 注解来增强的方法。继续看buildAspectJAdvisors方法。
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
重点看下获取切面增强的核心方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
遍历该类的每个方法,查找增强:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
查看方法是否配置了@Before等切面注解,随后把切面方法初始化为一个Advisor增强。
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
实例化增强方法:
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
实例化增强方法的具体实现:
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
return springAdvice;
}
经过了一层层的剥洋葱似的源码分析,终于找到了@Before等注解的处理的地方,不同的注解类型被实例化为不同类型的Advice对象, 不同类型的Advice对象被封装成了Advisor对象(实现类是:InstantiationModelAwarePointcutAdvisorImpl), 所以Advice或Advisor名字不同但其实表达的意思基本是一样的。
补充说明一下增强器的分类
在疑问中提出了这个问题,从代码上看是分IntroductionAdvisor 和PointcutAdvisor 两类的。 而我们通过@AspectJ注解方法的都是封装成了InstantiationModelAwarePointcutAdvisorImpl类,而它就是PointcutAdvisor, 所以一般关注PointcutAdvisor 类型就够了
总结获取增强器
1、获取候选增强器基本可以等同为吧标注了特殊注解的方法信息等封装为InstantiationModelAwarePointcutAdvisorImpl实例返回, 这个实例就代表了Advisor 增强 2、适配当前bean的增强器,本质就是通过matches方法比较method是不是符合切入点表达式的规则。 本质上是一个表达式语言的解析。
|