一、注解及标签开启 AOP 功能

这里的注解及标签指的是:@EnableAspectJAutoProxy 和 <aop:aspectj-autoproxy /> 。

1.1 @EnableAspectJAutoProxy

先来看看该注解对程序做了啥!

进入注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//引入AspectJAutoProxyRegistrar
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

/**
* 表明该类采用CGLIB代理还是使用JDK的动态代理
*/
boolean proxyTargetClass() default false;

/**
* 解决内部调用不能使用代理的场景 默认为false表示不处理
* true则表示这个代理对象的副本就可以通过AopContext.currentProxy()获得(ThreadLocal里面),
* 从而我们可以很方便得在Spring框架上下文中拿到当前代理对象(处理事务时很方便)
*/
boolean exposeProxy() default false;

}

该注解的最大作用就是向容器中注册了 AspectJAutoProxyRegistrar 类

org.springframework.context.annotation.AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//向容器注册了一个基于注解的自动代理创建器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
//表示强制指定了要使用CGLIB
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//表示强制暴露Bean的代理对象到AopContext
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}

}

AspectJAutoProxyRegistrar 是一个ImportBeanDefinitionRegistrar,前面讲过这种类型向容器中注入 Bean 的方式,不清楚的可以去回顾。

有代码可知,我们的关注点应该是想容器中注册的代理创建器,及下面代码。

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
// 最终向容器中注册了 AnnotationAwareAspectJAutoProxyCreator 类
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

可以看到,通过添加 @EnableAspectJAutoProxy 注解,实际在程序中是注册了一个 AnnotationAwareAspectJAutoProxyCreator 类型的 Bean,所以我们也很自然的想到我们的 AOP 功能就是它所提供的。

1.2

XML 配置文件中配置该标签则是干了些啥事呢!

我们直接来到解析 XML 配置文件的代码部分,如下:

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
// 解析默认的命名空间,既 beans 这种
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
// 解析非默认命名空间,既 aop、scan 这种
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}

我们细心观察会发现,<aop:aspectj-autoproxy /> 标签是属于非默认的命名空间,所以会走下面代码:

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement

public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 拿到节点ele的命名空间,例如常见的:
// <context> 节点对应命名空间: http://www.springframework.org/schema/context
// <aop> 节点对应命名空间: http://www.springframework.org/schema/aop
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// 拿到命名空间对应的的handler, 例如:http://www.springframework.org/schema/aop 对应 AopNamespaceHandler
// getNamespaceHandlerResolver: 拿到namespaceHandlerResolver
// resolve: 使用namespaceHandlerResolver解析namespaceUri, 拿到namespaceUri对应的NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 使用拿到的handler解析节点(ParserContext用于存放解析需要的一些上下文信息)
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

这里我们分析的是 AOP ,所以 NamespaceHandler 拿到的肯定是 AopNamespaceHandler。

那么,进入到 AopNamespaceHandler 源码:

org.springframework.aop.config.AopNamespaceHandler

public class AopNamespaceHandler extends NamespaceHandlerSupport {

@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
// 注册解析<aop:config> 配置
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 注册解析<aop:aspectj-autoproxy> 配置
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

}

我们看到这里有个 init 方法,那啥时候调用的呢!

这里我直接说答案,在 getNamespaceHandlerResolver 方法中会拿到我们的 XXXHandler 接着会调用 resolve 方法,而正是该方法的内部调用了 init 方法。

init 方法逻辑很简单,就是向容器中注册一些 Bean 信息,其中 AspectJAutoProxyBeanDefinitionParser 类型的 Bean 非常重要。

现在 Bean 信息有了,那么怎么去处理的呢,这就要看 parse 方法了。

org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse

public BeanDefinition parse(Element element, ParserContext parserContext) {
// 找到解析 parser 的 Bean,就是上面我们注册的 AspectJAutoProxyBeanDefinitionParser
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}

org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser#parse

public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册自动代理的处理器
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}

org.springframework.aop.config.AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 得到需要注册的自动代理处理器
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//设置是否强制使用Cglib和暴露proxy(这个后头会解释)
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册bean
registerComponentIfNecessary(beanDefinition, parserContext);
}

org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
// 注册 AnnotationAwareAspectJAutoProxyCreator 类
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

通过源码分析下来,原来 <aop:aspectj-autoproxy /> 标签要干的事情也是向容器中注入 AnnotationAwareAspectJAutoProxyCreator 类型的 Bean 啊!而上面我们也说了他是 AOP 功能的提供者。

1.3 图示

1.1 和 1.2 的简单执行流程图

Spring AOP源码分析二_spring

1.4 AnnotationAwareAspectJAutoProxyCreator

Spring AOP 功能的开启都源于这个类:AnnotationAwareAspectJAutoProxyCreator(自动代理创建器),所以这就是我们要重点分析的 AOP 功能类了。

类继承结构图

Spring AOP源码分析二_spring_02

还记得我们的 AOP 代理入口在哪里吗?

对,就是在初始化 Bean 的时候,如果有需要代理,则返回一个代理对象否则返回普通对象。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

// ...

// 应用后置处理器中的 postProcessAfterInitialization 方法返回代理对象(如果需要代理)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

// ...
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 拿到所有的后置处理器,并执行 postProcessAfterInitialization 方法
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

该方法会调用 AOP 的后置处理器,也既 AnnotationAwareAspectJAutoProxyCreator 类体系中的 postProcessAfterInitialization 方法。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 判断是否已经被代理过
if (!this.earlyProxyReferences.contains(cacheKey)) {
// Spring实现Bean代理的核心方法
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

这个方法就是我们分析整个 AOP 功能的入口了,不容器啊!真的是做了那么多的铺垫才找到这个入口的。

1.5 wrapIfNecessary

方法源码

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

/**
* Spring实现Bean代理的核心方法。wrapIfNecessary在两处会被调用,一处是getEarlyBeanReference(第三级缓存那块),
* 另一处是postProcessAfterInitialization
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 已经被处理过
// 判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 不需要被织入逻辑的
// 在advisedBeans缓存中存在,并且value为false,则代表无需处理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 是不是基础的 bean 是不是需要跳过的
// 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.
// 返回匹配当前Bean的所有Advice\Advisor\Interceptor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果存在增强器则创建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建Bean对应的代理,SingletonTargetSource用于封装实现类的信息
// 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
// 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 创建完代理后,将cacheKey -> 代理类的class放到缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象
return proxy;
}
// 该Bean是不需要进行代理的,下次就不需要重复生成了
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

这个方法干了些啥:

  1. 判断是否需要进行代理
  2. 解析切面类,将切面中的通知封装成具体的通知对象(shouldSkip)
  3. 返回匹配当前 Bean 的所有Advice\Advisor\Interceptor(getAdvicesAndAdvisorsForBean)
  4. 创建代理(createProxy)

好,下面我们就要分别对其进行分析了。

1.6 shouldSkip

该方法的本意是判断是否跳过 Bean 的代理,但其在判断过程中会将切面进行解析(事务在这里是不会解析)。

方法源码:

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 找到候选的 Advisors
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
// 如果增强的切面类名和beanName一致,那就跳过
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
// 调用父类判断是否跳过,默认不跳过
return super.shouldSkip(beanClass, beanName);
}

这个跳过方法虽然结果是返回 true/false ,但是显然重点不在这,而在 findCandidateAdvisors 方法。

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 当使用注解方式配置 AOP 的时候并不是丢弃了对 XML 配置的支持,在这里
// 调用父类方法加载配置文件中的 AOP 声明
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 解析 AspectJ 注解切面类
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}

这个方法中先是获取了一次 XML 配置中的 AOP 声明然后在去获取注解方式的 AOP 配置。

在 findCandidateAdvisors 方法中其实现很简单,就是从容器中获取 Advisor 类型的 Bean 并排除掉正在创建的 Bean ,并返回获得到的结果。

接下来会继续解析我们注解配置的 AOP 既 buildAspectJAdvisors ,这也是我们分析的重点,看下面源码:

org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
// 如果aspectNames为空,则进行解析
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
// 用于保存切面的名称的集合
aspectNames = new ArrayList<>();
// 获取所有的beanName
// AOP功能中在这里传入的是Object对象,代表去容器中获取到所有的组件的名称,然后再
// 进行遍历,这个过程是十分的消耗性能的,所以说Spring会再这里加入了保存切面信息的缓存。
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 遍历我们从IOC容器中获取处的所有Bean的名称
// 循环遍历所有的beanName,找出对应的增强方法
for (String beanName : beanNames) {
// 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator
// 实现了自己的逻辑,支持使用includePatterns进行筛选
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.
// 获取对应的bean的类型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 提取@Aspect注解标记的Class
if (this.advisorFactory.isAspect(beanType)) {
// 是切面类
// 加入到缓存中
// 将存在Aspect注解的beanName添加到aspectNames列表
aspectNames.add(beanName);
// 新建切面元数据
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// 获取per-clause的类型是SINGLETON
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// Aspect里面的advice和pointcut被拆分成一个个的advisor,
// advisor里的advice和pointcut是1对1的关系
// 解析标记AspectJ注解中的增强方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 单例则直接将Advisor类存到缓存
this.advisorsCache.put(beanName, classAdvisors);
}
else {
// 否则将其对应的工厂缓存
// 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法
this.aspectFactoryCache.put(beanName, factory);
}
// 将解析的增强器添加到advisors
advisors.addAll(classAdvisors);
}
else {
// 如果per-clause的类型不是SINGLETON
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
// 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
// 将factory放到缓存,之后可以通过factory来解析增强方法
this.aspectFactoryCache.put(beanName, factory);
// 解析标记AspectJ注解中的增强方法,并添加到advisors中
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
// 将解析出来的切面beanName放到缓存aspectBeanNames
this.aspectBeanNames = aspectNames;
// 最后返回解析出来的增强器
return advisors;
}
}
}
// 如果aspectNames不为null,则代表已经解析过了,则无需再次解析
// 如果aspectNames是空列表,则返回一个空列表。空列表也是解析过的,只要不是null都是解析过的。
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// aspectNames不是空列表,则遍历处理
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
// 根据aspectName从缓存中获取增强器
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
// 根据上面的解析,可以知道advisorsCache存的是已经解析好的增强器,直接添加到结果即可
advisors.addAll(cachedAdvisors);
}
else {
// 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中,
// 从aspectFactoryCache中拿到缓存的factory,然后解析出增强器,添加到结果中
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
// 返回增强器
return advisors;
}

这个方法都干了些啥:

  1. 从容器中获取所有 Bean
  2. 遍历 BeanName ,获取所有被 @Aspect 标记的类
  3. 提取 Aspect 类中的 Advisors
  4. 将提取的结果加入到缓存

方法的执行流程不难,下面我们接着看一下这个方法是如何获取切面中的增强的,即:this.advisorFactory.getAdvisors(factory) ,这行代码。

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取Aspect的类Class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取Aspect的类名
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校验切面类
validate(aspectClass);

// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
// 我们使用的是包装模式来包装我们的MetadataAwareAspectInstanceFactory
// 构建为MetadataAwareAspectInstanceFactory
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

List<Advisor> advisors = new ArrayList<>();
// 获取到切面类中的所有方法,但是该方法不会解析到标注了@PointCut注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 循环解析切面中的方法,获得对应方法的增强
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.
// 向增强集合首部添加 SyntheticInstantiationAdvisor 类型的增强
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}

// Find introduction fields.
// 处理Introduction相关的Advice
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}

return advisors;
}

这个方法的执行流程就是先获取切面类,然后校验 class 是否符合切面类型,紧接着获取该 class 中的所有方法,并挨个遍历获得的方法,通过对切面中的每个方法进行解析判断最终找到我们要的增强。

那么这里的重点有两部分:

  1. 获取切面中的所有方法
  2. 判断方法是否为增强方法,是则返回。

第一部分很简单了,通过反射既可以获取一个类中的所有方法,我们重点看第二部分,即:getAdvisor 方法。

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor

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;
}
// 实例化我们的切面Advisor对象
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

这个方法同样是两部分:

  1. 根据传入的方法判断其是否标注增强相关的注解
  2. 根据返回的 expressionPointcut 对象构建相应的增强对象

先看第一部:

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getPointcut

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 找到Advice注解标签,并解析注解标签里面的pointCut属性值存储在AspectJAnnotation里
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}

AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}

这个方法流程很简单,就是通过传入的方法判断其是否标注这些注解:Before.class、Around.class、After.class、AfterReturning.class、 AfterThrowing.class、Pointcut.class,如果有那么就是我们想要的增强方法反之则返回 null。

接着我们看看第二部分,实例化具体的增强对象:

org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#InstantiationModelAwarePointcutAdvisorImpl

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 当前的Pointcut表达式
this.declaredPointcut = declaredPointcut;
// 切面的class对象
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
// 切面方法的名称
this.methodName = aspectJAdviceMethod.getName();
// 切面方法的参数类型
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
// 切面方法对象
this.aspectJAdviceMethod = aspectJAdviceMethod;
// aspectj的Advisor工厂
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
// aspect的实例工厂
this.aspectInstanceFactory = aspectInstanceFactory;
// 切面的顺序
this.declarationOrder = declarationOrder;
// 切面的名称
this.aspectName = aspectName;
// 判断当前的切面对象是否需要延时加载
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 将切面中的通知构造为advice通知对象
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}

这个方法很容易就可以看出来是实例化 Advisor 对象的。该方法设置了很多 AOP 中相关的属性值,看代码也非常好理解,但其中有一个要拿出来分析,就是 instantiateAdvice 方法,它是去实例化我们的具体增强类型的(何种增强)。

org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice

private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
// 获取 Advice
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvice

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 获取我们的切面类的class对象
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;
// 判断标注在方法上的注解类型
switch (aspectJAnnotation.getAnnotationType()) {
// 前置通知 构建AspectJMethodBeforeAdvice
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 后置通知 AspectJAfterAdvice
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 返回通知 AspectJAfterReturningAdvice
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
// 异常通知 AspectJAfterThrowingAdvice
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
// 环绕通知 构建AspectJAroundAdvice
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// 是PointCut注解 那么就抛出异常 因为在外面传递进来的方法已经排除了Pointcut的方法
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}

// Now to configure the advice...
// 设置我们构建出来的通知对象的相关属性比如DeclarationOrder,
// 在代理调用的时候,责任链顺序上会用
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();

return springAdvice;
}

看到这里是不是真正的看到你所想要的东西了,对,就是在 switch 那一块。

switch 根据方法上的注解类型,创建出对应的增强:

  • AspectJMethodBeforeAdvice
  • AspectJAfterAdvice
  • AspectJAfterReturningAdvice
  • AspectJAfterThrowingAdvice
  • AspectJAroundAdvice

至此,我们的 AOP 增强方法是被解析出来了,接下来就是根据 Bean 和 前面表达式来进行匹配,找到匹配当前 Bean 的所有增强方法了。

1.7 getAdvicesAndAdvisorsForBean

这个方法在 wrapIfNecessary 中调用,用于返回匹配当前 Bean 的所有增强对象,源码如下:

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取 Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}

进入 findEligibleAdvisors 源码

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到Spring IoC容器中所有的候选Advisor,已经分析了
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 判断找到的Advisor能不能作用到当前的类上
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
// 对获取到的advisor进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

接着我们进入到 findAdvisorsThatCanApply 方法

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

//给其ThreadLocal<String>的成员变量 currentProxiedBeanName设置上正在创建动态代理的Bean
//以标注当前线程正在创建的动态代理是针对哪一个Bean的
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//委托AopUtils.findAdvisorsThatCanApply方法筛选出匹配Bean的Advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}

org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 首先处理引介增强(@DeclareParents)用的比较少可以忽略
// 判断Advisor对象是不是实现了IntroductionAdvisor
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 遍历所有的candidateAdvisors
for (Advisor candidate : candidateAdvisors) {
// 引介增强已经处理,直接跳过
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 正常增强处理,判断当前bean是否可以应用于当前遍历的增强器(bean是否包含在增强器的execution指定的表达式中)
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}

这个方法分情况处理了两种增强:

  • 引介增强(用的较少)
  • 正常增强

我们这里分析正常增强即 canApply(candidate, clazz, hasIntroductions) 代码,进入源码:

org.springframework.aop.support.AopUtils#canApply

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
// 判断是否是IntroductionAdvisor
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
// 判断是否是PointcutAdvisor
else if (advisor instanceof PointcutAdvisor) {
// 转为PointcutAdvisor类型
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
// 如果Advisor连Pointcut表达式都没有的话,就证明它是匹配所有Bean的
return true;
}
}

方法分两种情况处理 advisor ,如果是 IntroductionAdvisor 则直接进行 matches 方法(下面会介绍)进行匹配,否则再调用 canApply 方法进行后续处理,那我们在进入该方法源码:

org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 对Bean进行初筛
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;
}

// 这里将MethodMatcher强转为IntroductionAwareMethodMatcher类型的原因在于,
// 如果目标类不包含Introduction类型的Advisor,那么使用
// IntroductionAwareMethodMatcher.matches()方法进行匹配判断时可以提升匹配的效率,
// 其会判断目标bean中没有使用Introduction织入新的方法,则可以使用该方法进行静态匹配,从而提升效率
// 因为Introduction类型的Advisor可以往目标类中织入新的方法,新的方法也可能是被AOP环绕的方法
// IntroductionAwareMethodMatcher的主要实现类是AspectJExpressionPointcut,可以看看里面的实现
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
// 判断匹配器是不是IntroductionAwareMethodMatcher
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}

Set<Class<?>> classes = new LinkedHashSet<>();
// 判断当前class是不是代理的class对象
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
// 获取到targetClass所实现的接口的class对象,然后加入到集合中
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 通过methodMatcher.matches来匹配方法
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 通过方法匹配器进行匹配
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}

return false;
}

这个方法匹配逻辑就有点绕了,先是对 Bean 进行初步的筛选,然后判断切入点表达式是否是切入所有方法,紧接着转换匹配器为 IntroductionAwareMethodMatcher 类型继续筛选,直到最终获匹配完成返回。

上面这两个方法都涉及到 matches 方法的筛选,那么我们进去看看是如何运作的。

org.springframework.aop.aspectj.AspectJExpressionPointcut#matches(java.lang.Class<?>)

public boolean matches(Class<?> targetClass) {
// 获取类里的pointcut表达式
PointcutExpression pointcutExpression = obtainPointcutExpression();
try {
try {
// 对被代理对象做类级别的初筛,只能匹配部分表达式(如within),
// 不支持execution等表达式的部分写法
// 对于精确到类上的execution表达式,该方法是支持精准匹配的
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
if (fallbackExpression != null) {
return fallbackExpression.couldMatchJoinPointsInType(targetClass);
}
}
}
catch (Throwable ex) {
logger.debug("PointcutExpression matching rejected target class", ex);
}
return false;
}

matches 方法主要是拿到切入点表达式,然后封装为 PointcutExpression 对象,紧接着通过该对象调用 couldMatchJoinPointsInType 方法去匹配传入的 class ,进行匹配返回结果。

最后,画图小能手上线(getAdvicesAndAdvisorsForBean流程图)

Spring AOP源码分析二_java_03

好了,到此通过 matches 方法返回的结果为 true 那就是匹配到的增强,反之就不是,最终会找到 IOC 容器中所有匹配该 Bean 的增强,然后来到下面的创建代理流程。

1.8 createProxy

当所有切面被解析成一个个具体的增强且根据切入点表达式和 Bean 也找出了匹配该 Bean 的增强之后要做的事情就是,进行代理。

就是下面的方法:

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 如果 beanFactory 是 ConfigurableListableBeanFactory 的类型,暴露目标类
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建一个 ProxyFactory,当前ProxyCreator在创建代理时将需要用到的字段赋值到ProxyFactory中去
ProxyFactory proxyFactory = new ProxyFactory();
// 将当前的 AnnotationAwareAspectJAutoProxyCreator 对象的属性赋值给ProxyFactory对象
proxyFactory.copyFrom(this);
// 处理 proxyTargetClass 属性
// 如果希望使用 CGLIB 来代理接口,可以配置
// proxy-target-class="true",这样不管有没有接口,都使用 CGLIB 来生成代理:
// <aop:config proxy-target-class="true"></aop:config>
if (!proxyFactory.isProxyTargetClass()) {
// 检查preserveTargetClass属性,判断beanClass是应该基于类代理还是基于接口代理
if (shouldProxyTargetClass(beanClass, beanName)) {
// 如果是基于类代理,则将proxyTargetClass赋值为true
proxyFactory.setProxyTargetClass(true);
}
else {
// 评估bean的代理接口
// 有接口的,调用一次或多次:proxyFactory.addInterface(ifc);
// 没有接口的,调用:proxyFactory.setProxyTargetClass(true);
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}

// 这个方法主要来对前面传递进来的横切逻辑实例进行包装
// 注意:如果 specificInterceptors 中有 Advice 和 Interceptor,它们也会被包装成 Advisor
// 方法会整理合并得到最终的advisors (毕竟interceptorNames还指定了一些拦截器的)
// 至于调用的先后顺序,通过方法里的applyCommonInterceptorsFirst参数可以进行设置,
// 若applyCommonInterceptorsFirst为true,interceptorNames属性指定的Advisor优先调用。默认为true
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 将advisors添加到proxyFactory
proxyFactory.addAdvisors(advisors);
// 设置要代理的类,将targetSource赋值给proxyFactory的targetSource属性,之后可以通过该属性拿到被代理的bean的实例
proxyFactory.setTargetSource(targetSource);
// 这个方法是交给子类的,子类可以继续去定制此proxyFactory
customizeProxyFactory(proxyFactory);

// 用来控制proxyFactory被配置之后,是否还允许修改通知。默认值为false(即在代理被配置之后,不允许修改代理类的配置)
proxyFactory.setFrozen(this.freezeProxy);
// 设置preFiltered的属性值,默认是false。子类:AbstractAdvisorAutoProxyCreator修改为true
// preFiltered字段意思为:是否已为特定目标类筛选Advisor
// 这个字段和DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice获取所有的Advisor有关
// CglibAopProxy和JdkDynamicAopProxy都会调用此方法,然后递归执行所有的Advisor
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

// 使用proxyFactory获取代理
return proxyFactory.getProxy(getProxyClassLoader());
}

该方法的主要流程如下:

  1. 判断代理的方式,JDK还是CGLIB
  2. 封装 specificInterceptors 为 Advisor
  3. 通过 proxyFactory 获取代理

那,现在一个个来分析。

一、判断代理方式

org.springframework.aop.framework.ProxyProcessorSupport#evaluateProxyInterfaces

/**
* 这里决定了如果目标类没有实现接口直接就是Cglib代理
* 检查给定beanClass上的接口们,并交给proxyFactory处理
*/
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 找到该类实现的所有接口们
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
// 标记:是否有存在合理的接口
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
//不管接口是否合理,都将其添加进去
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
proxyFactory.setProxyTargetClass(true);
}
}

这个方法通过类上的接口判断类是否实现接口且接口中是否有方法决定使用 JDK 还是 CGLIB 来进行代理。

二、封装 specificInterceptors 为 Advisor

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
// 解析interceptorNames而来获得Advisor数组
Advisor[] commonInterceptors = resolveInterceptorNames();

List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
// 添加参数传进来的,即前面解析出来的advisors
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
// 添加拦截器
// 调用的先后顺序,通过applyCommonInterceptorsFirst参数可以进行设置,
// 若applyCommonInterceptorsFirst为true,interceptorNames属性指定的Advisor优先调用。
// 默认为true
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
// 把拦截器包装为Advisor
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// wrap包装
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}

这个方法有一些细枝末节的处理,但总的来说就是一个包装,保证最后所有的增强都是 Advisor 类型。

三、通过 proxyFactory 获取代理

org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)

public Object getProxy(@Nullable ClassLoader classLoader) {
// 首先获取AopProxy对象,其主要有两个实现:JdkDynamicAopProxy和ObjenesisCglibAopProxy,
// 分别用于Jdk和Cglib代理类的生成,其getProxy()方法则用于获取具体的代理对象
// 1.createAopProxy:创建AopProxy
// 2.getProxy(classLoader):获取代理对象实例
return createAopProxy().getProxy(classLoader);
}

一、我们先进入 createAopProxy() 方法

org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy

protected final synchronized AopProxy createAopProxy() {
// 主要是为了激活AdvisedSupportListener监听器
if (!this.active) {
activate();
}
// 创建AopProxy
return getAopProxyFactory().createAopProxy(this);
}

进入创建方法 createAopProxy

org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断使用JDK动态代理还是Cglib代理
// optimize:用于控制通过cglib创建的代理是否使用激进的优化策略。除非完全了解AOP如何处理代理优化,
// 否则不推荐使用这个配置,目前这个属性仅用于cglib代理,对jdk动态代理无效
// proxyTargetClass:默认为false,设置为true时,强制使用cglib代理,设置方式:<aop:aspectj-autoproxy proxy-target-class="true" />
// hasNoUserSuppliedProxyInterfaces:config是否存在代理接口或者只有SpringProxy一个接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 拿到要被代理的对象的类型
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
// TargetSource无法确定目标类:代理创建需要接口或目标。
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 要被代理的对象是接口 || targetClass是Proxy class 已经是个JDK的代理类(Proxy的子类,所有的JDK代理类都是此类的子类)
// 当且仅当使用getProxyClass方法或newProxyInstance方法动态生成指定的类作为代理类时,才返回true。
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// JDK动态代理,这边的入参config(AdvisedSupport)实际上是ProxyFactory对象
// 具体为:AbstractAutoProxyCreator中的proxyFactory.getProxy发起的调用,在ProxyCreatorSupport使用了this作为参数,
// 调用了的本方法,这边的this就是发起调用的proxyFactory对象,而proxyFactory对象中包含了要执行的的拦截器
return new JdkDynamicAopProxy(config);
}
// Cglib代理
return new ObjenesisCglibAopProxy(config);
}
else {
// JDK动态代理
return new JdkDynamicAopProxy(config);
}
}

这个方法就是创建代理的最底层实现逻辑了,通过一系列的判断最终返回 JdkDynamicAopProxy 或 ObjenesisCglibAopProxy 对象。

二、接着进入 getProxy(classLoader) 方法

因为上面会返回两种不同的代理对象,所以这里的方法也要分为两种:

  • JdkDynamicAopProxy.getProxy(classLoader)
  • ObjenesisCglibAopProxy .getProxy(classLoader)

这里我以 JDK 的代理为主进行分析,所以进入 JdkDynamicAopProxy 类中。

org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)

public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 拿到要被代理对象的所有接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 通过classLoader、接口、InvocationHandler实现类,来获取到代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

好了,相信看到这行代码大家就豁然开朗了:Proxy.newProxyInstance ,那么到此呢,我们的代理对象也算是创建完毕了。

此时,画图小能手再次上线(createProxy 方法流程)

Spring AOP源码分析二_java_04

二、JDK 代理的执行流程

上面我们花费了非常多的篇幅分析了一个对象的代理流程,那么代理对象终归是要去执行我们的实际业务方法的,所以其代理对象的执行流程也是我们关注的一大重点。

那,还是一样,我只分析一下 JdkDynamicAopProxy 中的 invoke 方法(所有代理对象的方法执行都是执行这个方法)。

org.springframework.aop.framework.JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;
Object target = null;

try {
// 若是equals方法不需要代理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
// 若是hashCode方法不需要代理
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
// 如果当前方法是Spring织入的DecoratingProxy接口中的方法,则返回目标对象的Class类型
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 如果被代理的对象本身就实现了Advised接口,则证明该类里面的方法已经被代理了,直接执行即可
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

Object retVal;
// 是否将动态代理暴露给AopContext
// 如果 `expose-proxy` 属性为 `true`,则需要暴露当前代理对象
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
// 向 AopContext 中设置代理对象,并记录 ThreadLocal 之前存放的代理对象
// 这样一来,在 Advice 或者被拦截方法中可以通过 AopContext 获取到这个代理对象
oldProxy = AopContext.setCurrentProxy(proxy);
// 标记这个代理对象被暴露了
setProxyContext = true;
}

// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// 获取我们的目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);

// Get the interception chain for this method.
// 获取能够应用于该方法的所有拦截器(有序)
// 不同的 AspectJ 根据 @Order 排序
// 同一个 AspectJ 中的 Advice 排序:AspectJAfterThrowingAdvice > AfterReturningAdviceInterceptor > AspectJAfterAdvice > AspectJAroundAdvice > MethodBeforeAdviceInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
// chain 是空的,说明不需要被织入横切逻辑,直接执行被代理的方法实例本身
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
// 获取目标对象的调用链逻辑,并且对该链进行调用
// 该对象就是 Joinpoint 对象
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 执行目标方法,以及所有的 MethodInterceptor 方法拦截器(Advice 通知器),并获取返回结果
retVal = invocation.proceed();
}

// Massage return value if necessary.
//获取目标方法返回值类型
Class returnType = method.getReturnType();
//如果需要返回代理对象
if (retVal != null // 返回值不为空
&& retVal == target // 返回值就是当前目标对象
&& returnType != Object.class // 返回值类型不是 Object 类型
&& returnType.isInstance(proxy) // 返回值类型就是代理对象的类型
&& !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())){
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
// 判断返回值如果为目标对象,并且当前方法的返回值类型是当前代理对象的类型,那么就将
// 当前代理对象返回。这里的逻辑的实际意思简单的说就是,如果返回值是目标对象,那么
// 就将当前代理对象返回
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
// 如果返回值满足其为空,不是Void类型,并且是基本数据类型,那么就抛出异常,
// 因为基本数据类型的返回值必然不为空
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
// 如果目标对象不为空,且 TargetSource 不是静态的(表示每次都得返回一个新的目标对象)
// 那么需要释放当前获取到的目标对象,通常情况下我们的单例 Bean 对应的都是 SingletonTargetSource,不需要释放
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
// 如果暴露了当前代理对象,则需要将之前的代理对象重新设置到 ThreadLocal 中
AopContext.setCurrentProxy(oldProxy);
}
}
}

这个方法干了些啥:

  1. 判断执行方法是否需要执行代理
  2. 获取方法执行链
  3. 执行 chain

这个 invoke 方法,我们只要关注两点就可以了:

  • 获取增强的执行链
  • 根据执行链,执行方法

2.1 获取执行链

这个步骤好理解,就是把符合该方法的增强方法都放到一个拦截器链上,后面只要根据这个链依次执行方法就行。

方法源码:

org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice

/**
* 将之前注入到advisorChain中的advisors转换为MethodInterceptor
* 和InterceptorAndDynamicMethodMatcher集合
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
//尝试从缓存获取
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//缓存没有,则尝试通过advisorChainFactory去创建调用链
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
//将获取到的结果加入到缓存中
this.methodCache.put(cacheKey, cached);
}
return cached;
}

进入 getInterceptorsAndDynamicInterceptionAdvice 方法获取数据

org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {

// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 遍历上一步获取到的 Advisor
// 筛选出哪些 Advisor 需要处理当前被拦截的 `method`,并获取对应的 MethodInterceptor(Advice,如果不是方法拦截器则会包装成对应的 MethodInterceptor)
for (Advisor advisor : config.getAdvisors()) {
// 如果是 PointcutAdvisor 类型,则需要对目标对象的类型和被拦截的方法进行匹配
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 判断这个 PointcutAdvisor 是否匹配目标对象的类型,无法匹配则跳过
// AdvisedSupport 是否已经过滤过目标对象的类型
// 调用 Pointcut 的 ClassFilter 对目标对象的类型进行匹配
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//从 Advisor 中获取 Advice,并包装成 MethodInterceptor 拦截器对象(如果不是的话)
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 获取 Pointcut 的 MethodMatcher 方法匹配器对该方法进行匹配
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
//若 MethodMatcher 的 `isRuntime()` 返回 `true`,则表明 MethodMatcher 要在运行时做一些检测
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
//将上面获取到的 MethodInterceptor 和 MethodMatcher 包装成一个对象,并添加至 `interceptorList`
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
// 否则,直接将 MethodInterceptor 们添加至 `interceptorList`
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 否则,如果是 IntroductionAdvisor 类型,则需要对目标对象的类型进行匹配
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
// 判断这个 IntroductionAdvisor 是否匹配目标对象的类型,无法匹配则跳过
// AdvisedSupport 是否已经过滤过目标对象的类型
// 调用 Pointcut 的 ClassFilter 对目标对象的类型进行匹配
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
// 从 Advisor 中获取 Advice,并包装成 MethodInterceptor 拦截器对象(如果不是的话)
Interceptor[] interceptors = registry.getInterceptors(advisor);
// 直接将 MethodInterceptor 们添加至 `interceptorList`
interceptorList.addAll(Arrays.asList(interceptors));
}
}
// 否则,不需要对目标对象的类型和被拦截的方法进行匹配
else {
// 从 Advisor 中获取 Advice,并包装成 MethodInterceptor 拦截器对象(如果不是的话)
Interceptor[] interceptors = registry.getInterceptors(advisor);
// 直接将 MethodInterceptor 们添加至 `interceptorList`
interceptorList.addAll(Arrays.asList(interceptors));
}
}
// 返回 `interceptorList` 所有的 MethodInterceptor 拦截器
// 因为 Advisor 是排好序的,所以这里的 `interceptorList` 是有序的
return interceptorList;
}

该方法执行的主要逻辑就是获取 method 对象的增强集合。

具体执行逻辑就是获取所有的增强(Advisor),并分三种情况分别处理这些 Advisor:

  1. PointcutAdvisor 类型增强:需要对目标对象的类型和被拦截的方法进行匹配
  2. IntroductionAdvisor 类型增强:需要对目标对象的类型进行匹配
  3. 上两者都不是的类型增强:不需要对目标对象的类型和被拦截的方法进行匹配

将上面获取的三种结果方法同一个集合当中并返回出去,这就是方法的执行链。到此我们的获取方法的执行链流程就分析完毕,紧接着就是如何具体的去执行这些方法及执行链了。

2.2 执行方法

下面我们来看方法的执行逻辑

// 创建代理对象目标方法的调用器,包含方法对应的 MethodInterceptor 拦截器链
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();

首先是创建出代理对象目标方法的调用器,源代码如下:

org.springframework.aop.framework.ReflectiveMethodInvocation#ReflectiveMethodInvocation

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

/** 代理对象 */
protected final Object proxy;
/** 目标对象 */
@Nullable
protected final Object target;
/** 目标方法 */
protected final Method method;
/** 方法入参 */
protected Object[] arguments;
/** 目标对象的 Class 对象 */
@Nullable
private final Class targetClass;
/** 自定义属性 */
@Nullable
private MapuserAttributes;
/** 方法的拦截器链路 */
protected final List interceptorsAndDynamicMethodMatchers;
/** 当前已经执行完的拦截器的位置索引,执行完则执行目标方法 */
private int currentInterceptorIndex = -1;

protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class targetClass, ListinterceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
// 获取目标方法,如果是桥接方法则会找到目标方法
this.method = BridgeMethodResolver.findBridgedMethod(method);
// 对该方法参数进行适配处理(如果有必要)
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
}

这个方法没别的作用就是创建对象,设置相关属性,以便于调用执行链执行方法。

紧接着看执行方法源码(proceed):

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 如果当前已经执行完的拦截器的位置索引就是最后一个,那么即可执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行目标方法(底层反射机制)
return invokeJoinpoint();
}

// 按顺序获取拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
/**
*如果是 InterceptorAndDynamicMethodMatcher 类型,表示 MethodMatcher 在真正的执行时需要做一些检测
* 参考 {@link DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice }
*/
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 通过 MethodMatcher 对目标方法进行匹配
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
// 匹配通过,则执行这个拦截器,并传递当前对象
return dm.interceptor.invoke(this);
}
// 否则,直接跳过这个拦截器
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 否则执行这个拦截器,并传递当前对象
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

该方法会按顺序获取 this.interceptorsAndDynamicMethodMatchers 集合当中的增强对象,挨个执行其 invoke 。

interceptorsAndDynamicMethodMatchers 集合中的元素执行顺序如下:

一、ExposeInvocationInterceptor

public class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {

public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}

}

二、AspectJAfterThrowingAdvice

public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {

public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
// 执行 afterThrowing 方法
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
}

三、AfterReturningAdviceInterceptor

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
// 执行 afterReturning 方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}

}

四、AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {

public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
// 执行 After 方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
}

五、MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
// 它会去执行我们的业务方法
return mi.proceed();
}
}

六、AspectJMethodBeforeAdvice

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
// 执行 before 方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}

最后,画图小能手上线,JDK 代理对象执行流程图如下:

Spring AOP源码分析二_spring_05

增强对类结构图及拦截器链

Spring AOP源码分析二_后端_06

至此,我们的 SpringAOP 流程全部分析完毕!