AOP的源码走读

aop源码

又撸了一边AOP的源码 ,做一下整理 (可能比较乱 就自己能看懂)我是通过注解的形式打断点来看的 像配置类开启AOP 打注解@EnableAspectJAutoProxy 切入的的类 @Aspect 和@Pointcut @Before 这些我就不表述了

我主要记住一下源码的关键步骤 以及思路
一:解析切面
二:创建动态代理
三:调用

------关于 AOP 到解析的开始的调用过程 start-------------------------

1.org.springframework.context.support.AbstractApplicationContext#refresh -----启动IOC
2.org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization ---- 实例化我们剩余的单实例bean.
finishBeanFactoryInitialization 方法中的 {
//实例化剩余的单实例bean
beanFactory.preInstantiateSingletons();

3.org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
4.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
5.org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
doGetBean 方法中的 {
//进入创建bean的逻辑
return createBean(beanName, mbd, args);
}
6.org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
createBean方法中的{
/**

  • 第1个bean后置处理器
  • 通过bean的后置处理器来进行后置处理生成代理对象,一般情况下在此处不会生成代理对象
  • 为什么不能生成代理对象,不管是我们的jdk代理还是cglib代理都不会在此处进行代理,因为我们的
  • 真实的对象没有生成,所以在这里不会生成代理对象,那么在这一步是我们aop和事务的关键,因为在这里
  • 解析我们的aop切面信息进行缓存
    /
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

    8.org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
    resolveBeforeInstantiation方法中的{
    /
    *
  • 后置处理器的【第一次】调用 总共有九处调用 事务在这里不会被调用,aop的才会被调用
  • 为啥aop在这里调用了,因为在此处需要解析出对应的切面报错到缓存中
    /
    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    //若InstantiationAwareBeanPostProcessors后置处理器的postProcessBeforeInstantiation返回不为null

    9.AbstractAutowireCapableBeanFactory类applyBeanPostProcessorsBeforeInstantiation 方法的代码
    @Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    /
    *
    • 获取容器中的所有后置处理器
      /
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
      //判断后置处理器是不是InstantiationAwareBeanPostProcessor
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
      //把我们的BeanPostProcessor强制转为InstantiationAwareBeanPostProcessor
      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
      /
      *
      * 【很重要】
      * 我们AOP @EnableAspectJAutoProxy 为我们容器中导入了 AnnotationAwareAspectJAutoProxyCreator
      * 我们事务注解@EnableTransactionManagement 为我们的容器导入了 InfrastructureAdvisorAutoProxyCreator
      * 都是实现了我们的 BeanPostProcessor接口,InstantiationAwareBeanPostProcessor,
      * 进行后置处理解析切面
      */
      Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
      if (result != null) {
      return result;
      }
      }
      }
      return null;
      }
  1. org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation – 解析当前Bean的切面
    ------关于 AOP 到解析的开始的调用过程 end-------------------------

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
List advisors = super.findCandidateAdvisors(); ---- 是以前接口的方式 注解的方式 集合返回的是0
@Override
protected List findCandidateAdvisors() {
// 找出xml配置的Advisor和原生接口的AOP的Advisor 找出事务相关的advisor
List advisors = super.findCandidateAdvisors();
//找出Aspect相关的信息之后封装为一个advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
//返回我们所有的通知
return advisors;
}

postProcessBeforeInstantiation 方法把 advisors 放到缓存中

------关于 生成aop代理过程 Start-------------------------

/*生成aop代理

  • 在该后置方法中 我们的事务和aop的代理对象都是在这生成的
    org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization在postProcessAfterIinitialization进行生成代理
    /**
  • 生成aop代理
  • 在该后置方法中 我们的事务和aop的代理对象都是在这生成的
  • @param bean bean实例
  • @param beanName bean的名称
  • @return
  • @throws BeansException
    */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
    if (bean != null) {
    //获取缓存key
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    // 之前循环依赖创建的动态代理 如果是现在的bean 就不再创建,,并且移除
    if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    // 该方法将会返回动态代理实例
    return wrapIfNecessary(bean, beanName, cacheKey);
    }
    }
    return bean;
    }

wrapIfNecessary方法的
// 根据当前bean找到匹配的advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

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

/**

  • 找到和当前bean匹配的advisor
    /
    List advisors = findEligibleAdvisors(beanClass, beanName);
    org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
    org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
    org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
    /
    *
  • 真正的判断我们的事务增强器是不是我们合适的
    */
    org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
    //找到真正能用的增强器
    return canApply(pca.getPointcut(), targetClass, hasIntroductions);

org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean) – 进行粗筛
// 进行类级别过滤(通过AspectJ) --粗筛
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}

org.springframework.aop.aspectj.AspectJExpressionPointcut#matches(java.lang.Class<?>) 上面代码的类

org.springframework.aop.aspectj.AspectJExpressionPointcut#obtainPointcutExpression

org.springframework.aop.aspectj.AspectJExpressionPointcut#initializePointcutParser – 得到切点解析器 得到一个 PointcutExpression

org.aspectj.weaver.tools.PointcutExpression#couldMatchJoinPointsInType — 调用这个方法 进行粗筛

//循环所有的class对象
for (Class<?> clazz : classes) {
//通过class获取到所有的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
//循环我们的方法
for (Method method : methods) {
//通过methodMatcher.matches来匹配我们的方法
if (introductionAwareMethodMatcher != null ?
// 通过切点表达式进行匹配 AspectJ方式 调用这个方法进行精筛
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 通过方法匹配器进行匹配 内置aop接口方式
methodMatcher.matches(method, targetClass)) {
// 只要有1个方法匹配上了就创建代理
return true;
}
}
}

org.springframework.aop.IntroductionAwareMethodMatcher#matches – 调用这个方法进行精筛 只要有一个匹配上了 就返回true 返回到
org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply 方法下的 CanApply方法 Advisor 加入到 eligibleAdvisors 集合中
/**

  • 真正的判断我们的事务增强器是不是我们合适的
    */
    if (canApply(candidate, clazz, hasIntroductions)) {
    eligibleAdvisors.add(candidate);
    }

eligibleAdvisors 回到 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 方法中会进行加上一个 内置的 ExportInvocation 的Advisor List 索引是0
protected List findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 拿到接口方式的AOP (这次是从缓存中拿了)
List candidateAdvisors = findCandidateAdvisors();
//判断我们的通知能不能作用到当前的类上(切点是否命中当前Bean)
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors); ---- - 这里加入了一个和 内置的 ExportInvocation 的Advisor
//对我们的advisor进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

再进行排序 索引大的放在前面 ( 多个切面就根据实现了 order注解的数字 小的在前面)

最后根据 eligibleAdvisors 这个集合 的数量 大于 0 则证明可以创建动态代理

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy — 创建动态代理 (createProxy 是wrapIfNecessary方法内的)
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy 在这个方法中会判断是用 JDK动态代理 还是 cglib动态代理

设置了ProxyTargetClass就会用cglib动态代理
如果没有设置,并且有实现接口就会用JDK动态代理
通过代理工厂得到动态代理 放到一级缓存当中

------关于 生成aop代理过程 End-------------------------

------关于 调用动态代理过程 Start-------------------------
以JDK动态代理为例子:
调用的时候 从bean里面拿到的就是一个动态代理的实现, 在调用方法的时候 就会进入到 org.springframework.aop.framework.JdkDynamicAopProxy#invoke
JdkDynamicAopProxy 的 invoke方法中
会进行一些判断:
//若执行代理对象的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();
}
//若执行的class对象是DecoratingProxy 则不会对其应用切面进行方法的增强。返回源目标类型
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);
}

如: 是否是执行对象的equals方法 、 是否执行的是hashCode方法 、执行的class对象是DecoratingProxy对象 、是否实现了目标对象实现的Advised接口

再判断一下 exposeProxy = true

接着 把我们的aop的advisor 全部转化为interceptorList, 通过责任链模式 依此调用
//把我们的aop的advisor 全部转化为拦截器, 通过责任链模式 依此调用
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

责任链 调用调用org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
proceed 这个方法

------关于 调用动态代理过程 End-------------------------

最后提出几个问题
问题一:Aop解析是在第一个bean的后置处理器进行解析的 那是哪个一个bean?
答:
是 AnnotationAwareAspectJAutoProxyCreator 这个bean 的后置处理器进行解析切面
把带有AspectJ这个注解的类
下面对应的@before @afrer等这些注解的方法 解析成一条条的 Advisor (Advisor中带有 Advice Pointcut )
Advice — 通知
Pointcut 有表达式 回去匹配 匹配到了 就回去创建动态代理

问题二: aop 在哪个方法创建动态代理?

正常的bean 在初始化之后
循环依赖的在getSingleton的时候 (循环依赖会设置一个smarInstantiationAwareBeanPostProcesor.getEarlyBeanrRefence)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值