先上一个AnnotationAwareAspectJAutoProxyCreator处理器的类图
主要关注左半部分处理器接口,重点是InstantiationAwareBeanPostProcessor接口定义的postProcessBeforeInstantiation和postProcessAfterInstantiation方法,即Bean实例化前和实例化后处理方法。
postProcessBeforeInstantiation前置方法
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
//查缓存,是否有处理过了,不管是不是需要通知增强的,只要处理过了就会放里面
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// isInfrastructureClass 是否是内部基础类 -- Advice Pointcut Advisor AopInfrastructureBean
// 是否有@Aspect注解 、就是没有ajc$开头的属性名
// shouldSkip 找出Aspect切面和解析通知器的方法,通知器Advisor里面有通知Advice实例
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
//要跳过的直接设置FALSE
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
这里关注shouldSkip方法,就是判断当前bean是否需要被代理。里面会收集所有通知器并缓存起来。
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// findCandidateAdvisors寻找通知器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 如果当前类是通知器类了,则返回true,外面需要advised的缓存设置为false,标识通知器类是不需要被处理的。
// 也就是说,如果定义的pointcut范围内包含Aspect的定义类,该类不会被切面处理
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 父类的,先找是否已存在Advisor的bean定义,有的话创建出来添加到集合中。
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
//寻找@Aspect注解的切面对象,然后解析他的方法,通过注解来生成对应的通知器Advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
父类的findCandidateAdvisors方法主要是Spring内置的,可以暂时不用关心,spring事务的通知器是在这里注入的。重点是
this.aspectJAdvisorsBuilder.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<>();
//寻找所有object类型的bean定义名字
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
//遍历获取有Aspect注解的加入到aspectNames列表
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 判断bean是否被@Aspect注解注释,如果是,代表是一个切面定义类
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);
// 这里解析对应的切面配置,就是反射遍历方法列表,找到除@Pointcut注解的方法
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 {
// Per target or per this.
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;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
// 从缓存里取
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
说明两点:
- 有缓存,也就是说只会加载一次。写入到缓存map中后,后面都是尽量从map中取
- 通过advisorFactory工厂获取对应的Advisor实例
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors
/**
1. 获取切面类型,然后获取除Pointcut注解的所有方法,根据方法注解来创建Advisor通知器
*/
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//获取切面
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
//验证
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//getAdvisorMethods获取通知器方法 非Pointcut注解的
for (Method method : getAdvisorMethods(aspectClass)) {
//创建Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) {
// @DeclareParents注解的属性
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
这里看几个方法:
- getAdvisorMethods(aspectClass)
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
// doWithMethods包含父类
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
// 做了个排序 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class, 普通的方法
methods.sort(METHOD_COMPARATOR);
return methods;
}
剔除了@Pointcut注解的方法 – Pointcut切面定义是为了匹配时使用,在后面匹配的时候会加载,这里只是加载Advisor方法,故需要剔除
排序,这里定义了各种Advisor的排序规则
2.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)
@Override
@Nullable
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;
}
// 建立method和所对应的pointcut方法的关系, 比如测试的类中doAround方法->doService()
// 也就是说Advisor通知器只是切面方法和切面定义的关系,
// pointcut表达式的解析不在这里,就是PointcutExpression还没有赋值
// 解析这部分是在后面使用时,获取方法匹配器前解析
// 构造方法里有个instantiateAdvice 初始化Advice通知对象
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
看一下Advice的初始化方法,里面有创建Advisor的
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvice
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//通知类型
// 通知对象最后被定义为AspectJAroundAdvice AspectJMethodBeforeAdvice
// AspectJAfterAdvice AspectJAfterReturningAdvice AspectJAfterThrowingAdvice
// 这5种类型 AOP最终都是这5类做的增强
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);
}
// Now to configure the advice...
//切点名
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
// 绑定参数
springAdvice.calculateArgumentBindings();
return springAdvice;
}
可以看到每一种类型对应一个Advisor
至此前置方法基本分析完了,总结一下就是加载Aspect类,解析生成对应的Advisor实例放入缓存供后续使用