参考文章:
前文:
目录
一、postProcessAfterInitialization
1、postProcessAfterInitialization
7、findAspectJAnnotationOnMethod
8、InstantiationModelAwarePointcutAdvisorImpl
写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。
在前文中,我们注册了代理类的自动创建类AnnotationAwareAspectJAutoProxyCreator,该类继承了BeanPostProcessor 接口,在AbstractAutoProxyCreator类中重写了postProcessAfterInitialization方法,进而实现了对正在创建中的bean实例的代理。
一、postProcessAfterInitialization
1、postProcessAfterInitialization
根据我们之前介绍的bean的生命周期可以得知,每一个bean 在初始化后都会去调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法。重写了的方法会判断该类是否不在缓存中,如不在则进行判断是否需要代理。之前我们介绍了三层缓存,该类重写了getEarlyBeanReference方法,因此可能存在已经被代理了的类。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
// 如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 判断当前bean是否需要被代理,如果需要则进行封装(earlyProxyReferences中缓存的是已经创建好的代理对象)
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
getCacheKey用来获取bean的原始类型,如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName。
protected Object getCacheKey(Class<?> beanClass, String beanName) {
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}
else {
return beanClass;
}
}
2、wrapIfNecessary
我们可以确认,wrapIfNecessary方法就是创建代理类的核心方法。该方法中,我们依然时先检查缓存,确认缓存中没有,且不是aop的基础类,才会接着往下走。
首先会获取当前bean的Advices和Advisors,如果不为空,则调用createProxy方法去创建代理对象,加入缓存后将其返回给Spring容器。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 4.获取当前bean的Advices和Advisors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 5.如果存在增强器则创建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
// 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象
return proxy;
}
// 6.标记为无需处理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
3、findEligibleAdvisors
findEligibleAdvisors方法是真正的增强器查找方法,其内部实现了查询所有的增强器,然后再过滤出适用于当前bean上的,并将其返回。
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
// 1.找到符合条件的Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
// 2.如果没有符合条件的Advisor,则返回null
return DO_NOT_PROXY;
}
return advisors.toArray();
}
4、findEligibleAdvisors
这里接着上文,findEligibleAdvisors方法做了四件事:
(1)调用findCandidateAdvisors找出所有的Advisor.
(2)筛选第一步中获得到Advisor,找出适用于当前bean的。
(3)提供一个hook(钩子)方法,供子类实现用以拓展相关功能。
(4)将符合条件的Advisor进行排序。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1.查找所有的候选Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2.从所有候选的Advisor中找出符合条件的
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 3.扩展方法,留个子类实现
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 4.对符合条件的Advisor进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
二、findCandidateAdvisors
1、findCandidateAdvisors
findCandidateAdvisors方法调用父类的findCandidateAdvisors找出所有继承了advisor接口的实现类,然后调用aspectJAdvisorsBuilder.buildAspectJAdvisors()方法将使用了@Aspect注解的类构建成advisor,合并后返回。
// AnnotationAwareAspectJAutoProxyCreator.java
@Override
protected List<Advisor> findCandidateAdvisors() {
// 1.走父类AbstractAdvisorAutoProxyCreator实现的findCandidateAdvisors
List<Advisor> advisors = super.findCandidateAdvisors();
// 2.为bean工厂中的所有AspectJ注解类中的方法构建advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
2、findAdvisorBeans
上文中的findCandidateAdvisors最后会溯源到BeanFactoryAdvisorRetrievalHelper类的findAdvisorBeans()方法。
这里 findAdvisorBeans() 方法不难理解:
(1)尝试从缓存中获取class类型为Advisor的bean的beanName没有则调用BeanFactoryUtils工具类的beanNamesForTypeIncludingAncestors方法根据类型查找beanName。
(2)遍历所有的advisorNames,筛选出符合要求的,跳过正在创建的,然后使用getBean获取对应beanName的实例。
public List<Advisor> findAdvisorBeans() {
// 1.确认advisor的beanName列表,优先从缓存中拿
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 1.1 如果缓存为空,则获取class类型为Advisor的所有bean名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
// 2.遍历处理advisorNames
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
// isEligibleBean()是提供的一个hook方法,用于子类对Advisor进行过滤,这里默认返回值都是true
if (isEligibleBean(name)) {
// 2.1 跳过当前正在创建的advisor
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
} else {
try {
// 2.2 通过beanName获取对应的bean对象,并添加到advisors
advisors.add(this.beanFactory.getBean(name, Advisor.class));
} catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
// 3.返回符合条件的advisor列表
return advisors;
}
3、buildAspectJAdvisors
调用BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()实现,该方法内容较多,我按照大的模块分成两部分。
public List<Advisor> buildAspectJAdvisors() {
1、缓存为空,手动获取所有的beanName并过滤和封装所需增强器
2、缓存不为空,则从缓存中获取出增强器
}
1、手动获取
List<String> aspectNames = this.aspectBeanNames;
// (1)试从缓存中获取aspectNames,若没有则手动获取
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
// (1.1)调用beanNamesForTypeIncludingAncestors方法获取到所有的bean
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// (1.2)遍历所有的beanName,判断该bean是否为子类定制的需要过滤的bean
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
//(1.3)获取当前遍历的bean的Class类型,并判断当前bean是否使用了@Aspect注解进行标注
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
// 将存在Aspect注解的beanName添加到aspectNames列表
aspectNames.add(beanName);
//(1.4)将该beanName加入到aspectNames缓存中,并新建元数据。元数据里包含了该bean的一些属性。
AspectMetadata amd = new AspectMetadata(beanType, beanName);
//(1.5)判断@Aspect注解中标注的是否为singleton类型,默认的切面类都是singleton类型
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// (1.6)使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//(1.7)通过封装的factory获取其Advice,如@Before,@After等等,并将这些Advice都解析并且封装为一个个的Advisor
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
(1.8)如果切面类是singleton类型,则将解析得到的Advisor进行缓存,如果不是单例,则将factory放到缓存,以便再次获取时可以通过factory来解析
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
} else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
} else {
//(1.9)如果@Aspect注解标注的beanName的Bean是单例,但切面实例化模型不是单例,则抛异常。
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
// (1.10)将当前BeanFactory和切面bean封装为一个多例类型的Factory,同时对当前bean和factory进行缓存
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
//(1.11)将解析出来的切面beanName放到缓存aspectBeanNames,并返回
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
2、从缓存中获取
// 如果aspectNames不为null,则代表已经解析过了,则无需再次解析
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
// 根据aspectName从缓存中获取Advisor集合
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
// 根据上面的解析,可以知道advisorsCache存的是已经解析好的Advisor,直接添加到结果即可
advisors.addAll(cachedAdvisors);
} else {
// 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中,
// 从aspectFactoryCache中拿到缓存的factory,然后解析出Advisor,添加到结果中
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
// 返回增强器
return advisors;
整理一下就是容器首先会过滤得到 BeanFactory 中所有标注有 @Aspect 的类,然后对该注解参数进行解析,判断其环绕的目标 bean 是单例的还是多例的。如果是单例的,则直接缓存封装后的Advisor到 advisorsCache 中;如果是多例的,则将生成 Advisor 的 factory 进行缓存,以便每次获取时都通过 factory 获取一个新的 Advisor。
4、getAdvisors
遍历当前切面类所有的方法,包括父类和父接口的方法,找到其中没有使用 @Pointcut 注解标注的方法,然后对找到的方法进行遍历,将其封装为一个 Advisor。
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 这边可以通过之前组装的元数据AspectMetadata属性获取当前切面类的Class类型
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取当前处理的切面类的名字
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校验切面类
validate(aspectClass);
// 将当前aspectInstanceFactory进行封装,这里LazySingletonAspectInstanceFactoryDecorator
// 使用装饰器模式,主要是对获取到的切面实例进行了缓存,保证每次获取到的都是同一个切面实例
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList<Advisor>();
// 获取所有的没有使用@Pointcut注解标注的方法,然后对其进行遍历
for (Method method : getAdvisorMethods(aspectClass)) {
// 判断当前方法是否标注有@Before,@After或@Around等注解,如果标注了,则将其封装为一个Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
// 如果增强器不为空,则添加到advisors
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// 如果Advisor不为空,并且是需要延迟初始化的bean,则在第0位位置添加一个同步实例化增强器(用以保证增强使用之前的实例化)
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 判断属性上是否包含有@DeclareParents注解标注的需要新添加的属性,如果有,则将其封装为一个Advisor
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
getAdvisorMethods用来查找切面类上的方法,但会跳过pointcuts。
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<Method>();
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}
});
Collections.sort(methods, METHOD_COMPARATOR);
return methods;
}
5、getAdvisor
针对@Before,@After 或 @Around等注解标注的方法,调用getPointcut方法读取其中的表达式参数,即切点信息,并生成增强器。
@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 校验切面类
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 获取当前方法中@Before,@After或者@Around等标注的注解,并且获取该注解的值
// 如:@Around("execution(* com.joonwhee.open.aop.*.*(..))")
// 将其封装为一个AspectJExpressionPointcut对象
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 根据切点信息生成增强器
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
6、getPointcut
解析传入进来的方法,读取该方法上的第一个Aspect相关注解(例如@Before。@After等),并封装成AspectJExpressionPointcut返回。
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)
// 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
// 如果方法没有使用AspectJ的注解,则返回null
if (aspectJAnnotation == null) {
return null;
}
// 使用AspectJExpressionPointcut实例封装获取的信息
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
// 提取得到的注解中的表达式,
// 例如:@Around("execution(* com.joonwhee.open.aop.*.*(..))"),得到:execution(* com.joonwhee.open.aop.*.*(..))
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
ajexp.setBeanFactory(this.beanFactory);
return ajexp;
}
7、findAspectJAnnotationOnMethod
该方法用来查找方法上的直接,返回第一个找到的。
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
// 设置要查找的注解类
Class<?>[] classesToLookFor = new Class<?>[]{
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
// 查找方法上是否存在当前遍历的注解,如果有则返回
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
8、InstantiationModelAwarePointcutAdvisorImpl
根据切点信息生成增强器,其中aspectJAdviceMethod负责保存用来进行增强的方法,instantiateAdvice实例化增强器。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 简单的将信息封装在类的实例中
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
// aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
// 是否需要延迟实例化
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
} else {
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 实例化增强器:根据注解中的信息初始化对应的增强器
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
9、instantiateAdvice
instantiateAdvice方法实际上是调用的ReflectiveAspectJAdvisorFactory的getAdvice方法。根据方法使用的aspectJ注解创建对应的增强器,比如@Before则生成AspectJMethodBeforeAdvice对象。
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
// ReflectiveAspectJAdvisorFactory.java
@Override
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 获取切面类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 校验切面类(重复校验第3次...)
validate(candidateAspectClass);
// 查找并返回方法的第一个AspectJ注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 如果我们到这里,我们知道我们有一个AspectJ方法。检查切面类是否使用了AspectJ注解
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
AbstractAspectJAdvice springAdvice;
// 根据方法使用的aspectJ注解创建对应的增强器
switch (aspectJAnnotation.getAnnotationType()) {
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;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// 配置增强器
// 切面类的name,其实就是beanName
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
// 获取增强方法的参数
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
// 如果参数不为空,则赋值给springAdvice
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
// 最后,返回增强器
return springAdvice;
}
这里提一下AspectJAfterAdvice、AspectJAfterThrowingAdvice、AspectJAroundAdvice这些增强器都继承了MethodInterceptor接口,增强器正是通过该接口的invoke方法生效的。
public interface MethodInterceptor extends Interceptor {
/**
* Implement this method to perform extra treatments before and
* after the invocation. Polite implementations would certainly
* like to invoke {@link Joinpoint#proceed()}.
* @param invocation the method invocation joinpoint
* @return the result of the call to {@link Joinpoint#proceed()};
* might be intercepted by the interceptor
* @throws Throwable if the interceptors or the target object
* throws an exception
*/
Object invoke(MethodInvocation invocation) throws Throwable;
}
三、findAdvisorsThatCanApply
1、findAdvisorsThatCanApply
遍历所有上文中查找出来的增强器,首先处理引介增强,这个用的很少,个人没见过,这种增强器能够将被代理类中没有的方法插入到代理类中。
然后再进行一次循环,这次将会对普通类型的增强器调用canapply方法进行判断,看其是否能够作用于当前正在生成的Bean上。
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
// 首先处理引介增强(@DeclareParents)用的比较少可以忽略https://www.cnblogs.com/HigginCui/p/6322283.html
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 遍历所有的candidateAdvisors
for (Advisor candidate : candidateAdvisors) {
// 引介增强已经处理,直接跳过
if (candidate instanceof IntroductionAdvisor) {
continue;
}
// 判断是否可以应用到当前bean类型
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
2、canApply
通过 ClassFilter 对类进行过滤和通过 MethodMatcher 对方法进行过滤。这里的 ClassFilter 其实主要指的是 @Aspect 注解中使用的切点表达式,而 MethodMatcher 主要指的是 @Before,@After 等注解中使用的切点表达式。
// AopUtils.java
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 获取当前Advisor的CalssFilter,并且调用其matches()方法判断当前切点表达式是否与目标bean匹配,
// 这里ClassFilter指代的切点表达式主要是当前切面类上使用的@Aspect注解中所指代的切点表达式
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 判断如果当前Advisor所指代的方法的切点表达式如果是对任意方法都放行,则直接返回
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
// 获取目标类的所有接口
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
// 遍历目标类上的接口方法
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 使用matches判断能否作用于该方法上
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
本文主要介绍了Advisor 增强器的获取与解析:
(1)即首先获取 BeanFactory 中所有实现了 Advisor 接口的 bean,然后获取 BeanFactory 中所有标注了 @Aspect 注解的 bean,解析该 bean 中的所有的切面逻辑,并且封装为一个个 Advisor,这两种方式得到的 Advisor 都有可能是最终会应用到目标 bean 上的切面逻辑。
(2)通过解析Advisor上的切点表达式,并逐个与当前bean进行匹配的方式过滤出所有适用当前bean中方法的增强器。