Spring源码分析第三弹 - AOP切面编程分析

143 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

终于到AOP了,前面没看懂的一定跟着代码多看,不然本篇文章容易迷路! 话不多说,万变不离其宗,先上图。

AOP时序图

AOP时序图

源码分析

1.初始化阶段 -> 匹配切点的方法

  • 回到上篇文章中的AbstractAutowireCapableBeanFactory.doCreateBean主要看依赖注入后面的代码
//找到这里
//依赖注入
populateBean(beanName, mbd, instanceWrapper);
//初始化bean里面的初始方法 AOP切面入口 本文主要看这个
exposedObject = initializeBean(beanName, exposedObject, mbd);

//初始容器时创建的Bean对象,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
   invokeAwareMethods(beanName, bean);
   return null;
  }, getAccessControlContext());
 }
 else {
        //调用所有实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口方法回调
        //为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
  invokeAwareMethods(beanName, bean);
 }

 Object wrappedBean = bean;
 if (mbd == null || !mbd.isSynthetic()) {
        //调用回调方法,为Bean实例初始化前做一些处理
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 }

 try {
        //文件中通过init-method属性指定的 或者 @PostConstruct
        //还有一些实现InitializingBean 会调用后置通知 afterPropertiesSet
        //MVC mapping在这里回调触发 下一篇MVC时讲解
  invokeInitMethods(beanName, wrappedBean, mbd);
 }
 catch (Throwable ex) {
  throw new BeanCreationException(
    (mbd != null ? mbd.getResourceDescription() : null),
    beanName, "Invocation of init method failed", ex);
 }
 if (mbd == null || !mbd.isSynthetic()) {
        //调用回调方法,为Bean实例初始化之后做一些处理 AOP代理主要走这个
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }
    //返回对象
 return wrappedBean;
}



//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  throws BeansException {

 Object result = existingBean;
 //遍历容器为所创建的Bean回调所有实现了BeanPostProcessor接口后置处理器
 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
  //为Bean实例对象在初始化之后做一些自定义的处理操作 接下来走这个
  Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
  if (current == null) {
   return result;
  }
  result = current;
 }
 return result;
}
  • 接下来就到了spring-aop包下的AbstractAutoProxyCreator#postProcessAfterInitialization -> wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  return bean;
 }
 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  return bean;
 }
 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  this.advisedBeans.put(cacheKey, Boolean.FALSE);
  return bean;
 }

 // Create proxy if we have advice.
 //如果存在advice 就创建代理类 先看获取advices链,再看创建代理对象
 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
 //如果这个数组不等于null
 //protected static final Object[] DO_NOT_PROXY = null;
 if (specificInterceptors != DO_NOT_PROXY) {
  //标识这个bean被有advice
  this.advisedBeans.put(cacheKey, Boolean.TRUE);
  //创建代理对象
  Object proxy = createProxy(
    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  this.proxyTypes.put(cacheKey, proxy.getClass());
  //返回的就是代理对象了
  return proxy;
 }

 this.advisedBeans.put(cacheKey, Boolean.FALSE);
 return bean;
}
  • 接下来看获取拦截器链advices的逻辑,往下到AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
  Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
 //找到符合资格的拦截器
 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
 if (advisors.isEmpty()) {
  return DO_NOT_PROXY;
 }
 return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //加载当前已配置的AOP列表
 List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //根据beanName去匹配 下面简单分析一下这个
 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
 extendAdvisors(eligibleAdvisors);
 if (!eligibleAdvisors.isEmpty()) {
        //排序
  eligibleAdvisors = sortAdvisors(eligibleAdvisors);
 }
    //返回执行责任链
 return eligibleAdvisors;
}
  • findAdvisorsThatCanApply 一直往下到 AopUtils.canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
 Assert.notNull(pc, "Pointcut must not be null");
 if (!pc.getClassFilter().matches(targetClass)) {
  return false;
 }

 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<>();
 if (!Proxy.isProxyClass(targetClass)) {
  classes.add(ClassUtils.getUserClass(targetClass));
 }
 classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

 for (Class<?> clazz : classes) {
        //获取所有的方法
  Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
  for (Method method : methods) {
            //断点调试走introductionAwareMethodMatcher.matches 接下来看这里
   if (introductionAwareMethodMatcher != null ?
     introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
     methodMatcher.matches(method, targetClass)) {
    return true;
   }
  }
 }
 return false;
}
  • introductionAwareMethodMatcher.matches -> AspectJExpressionPointcut.getShadowMatch
//找到这行 通过AOP规则验证这个方法是否满足切点
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);

如果满足当前配置的切点,则在AbstractAutoProxyCreator#wrapIfNecessary创建代理对象并返回,初始化阶段到这里就完成了,接下来继续分析创建代理源码,也就是代码织入阶段

2.代码织入阶段 ->创建动态代理

  • 回到AbstractAutoProxyCreator.wrapIfNecessary
//找到这一段
//获取拦截器链
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果不为空就创建代理对象
if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    //创建代理对象 接下来走这里!
    Object proxy = createProxy(
        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
}

//创建代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
 //创建代理工厂
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
 //包装执行器链
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    //原始class对象的信息 封装了一层SingletonTargetSource
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
 //创建代理-> 这里有两种创建代理的方法 CGLIB 和JDK 我们这里挑 JdkDynamicAopProxy看
    return proxyFactory.getProxy(getProxyClassLoader());
}
  • 接下来到ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
 return createAopProxy().getProxy(classLoader);
}

//createAopProxy -> ProxyCreatorSupport#createAopProxy
protected final synchronized AopProxy createAopProxy() {
 if (!this.active) {
  activate();
 }
 //传的是this
 return getAopProxyFactory().createAopProxy(this);
}

//得到jdk或者Cglib对象
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
 if (!NativeDetector.inNativeImage() &&
   (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
  //原始类信息
  Class<?> targetClass = config.getTargetClass();
  if (targetClass == null) {
   throw new AopConfigException("TargetSource cannot determine target class: " +
     "Either an interface or a target is required for proxy creation.");
  }
  if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
   //通过构造方法保存advice信息AdvisedSupport 
   return new JdkDynamicAopProxy(config);
  }
  return new ObjenesisCglibAopProxy(config);
 }
 else {
  return new JdkDynamicAopProxy(config);
 }
}

//已jdk代理为例
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
 Assert.notNull(config, "AdvisedSupport must not be null");
 if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
  throw new AopConfigException("No advisors and no TargetSource specified");
 }
 this.advised = config;
 //获取原始类的接口 JKD动态代理必须是有接口的
 this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
 findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

  • 接下来分析getProxy -> JdkDynamicAopProxy.getProxy
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);
 //很熟悉的创建代理方式 如果不理解先移步看动态代理
 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

至此代理对象就创建好了,返回到IOC容器中的就是代理对象了。

3.运行阶段 -> 动态代理的反射调用

  • 调用某个方法是拿到的是代理对象,贴下JdkDynamicAopProxy代理类
//上面看到这个,执行回调方法为 this ,那么就说明代理对象调用会走当前类的invoke方法
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

//接下来看invoker方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 Object oldProxy = null;
 boolean setProxyContext = false;
 //获取原始类封装SingletonTargetSource
 TargetSource targetSource = this.advised.targetSource;
 Object target = null;

 try {
  //一系列的判断删掉
  ......

  //获取到原始类
  target = targetSource.getTarget();
  //类信息
  Class<?> targetClass = (target != null ? target.getClass() : null);

  //chain 链/管道的意思 获取拦截器管道
  //一直往下跟 实际上就是包装了一下 同时存了缓存 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
  //interceptor 就是registry.getInterceptors(advisor);通过构造方法初始化前置 后置 异常
  List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  if (chain.isEmpty()) {
   //管道为空
   Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
   //直接通过反射调用原始类
   retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  }
  else {
   // We need to create a method invocation...
   MethodInvocation invocation =
     new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
   //开始调用管道 我们接下来走这里
   retVal = invocation.proceed();
  }

  //后面就是返回指定额处理了,先去掉
  。。。
 }
 finally {
  if (target != null && !targetSource.isStatic()) {
   // Must have come from TargetSource.
   targetSource.releaseTarget(target);
  }
  if (setProxyContext) {
   // Restore old proxy.
   AopContext.setCurrentProxy(oldProxy);
  }
 }
}
  • 接下来invocation.proceed() ->ReflectiveMethodInvocation.proceed()
//成员变量
//执行的管道调用链 上面通过构造方法赋值
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;


//开始责任链调用
public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
    //如果当前执行的下标等于执行的size-1 说明是到最后一个执行了 则执行原生调用方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        //这里面跟进去就是这个 return method.invoke(target, args);
        return invokeJoinpoint();
    }
 //下标+1 就是从0开始 默认值是-1
    Object interceptorOrInterceptionAdvice =
        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    //如果要动态匹配joinPoint
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // Evaluate dynamic method matcher here: static part will already have
        // been evaluated and found to match.
        InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
        //动态匹配:运行时参数是否满足匹配条件
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            //主要看前置后置和异常 传入的参数是this 
            //例如前置切面执行完会再次调用到该方法
            return dm.interceptor.invoke(this);
        }
        else {
            //继续递归
            return proceed();
        }
    }
    else {
        //如果不是 直接调用MethodInterceptor
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}
  • dm.interceptor.invoke(this) -> AspectJAfterAdvice.invoke 调用通知的方法,挑一个看吧
//调用之后 其他的可以自己了解
public Object invoke(MethodInvocation mi) throws Throwable {
 try {
  //反射调用原始类
  return mi.proceed();
 }
 finally {
  //调用返回后的切面方法
  invokeAdviceMethod(getJoinPointMatch(), null, null);
 }
}

总结

在容器初始化bean之后,回调到后置通知方法,aop正好实现后置通知方法,经过判断如果满足当前的配置切点则生成代理类并返回到IOC容器中。 创建代理类时会把原始类、调用链路等信息通过构造方法保存下来,在创建动态代理时newInstance时传入的回调handler类也是this,那么在调用该代理类时会到handler类的invoke方法 在invoke方法中通过递归以及增加下标的方法使调用链路执行反射调用,如果不能正常匹配到对应的Advice类,则在到最后一个时直接反射调用原始类并返回 如果能正常匹配到,例如上面的AspectJAfterAdvice则是先反射调用原始类,然后再调用后置切面方法,整个流程结束

至此整个AOP切面的源码就分析完了,看完这些代码,再手写一般简单的应没啥问题了吧! 下一节MVC源码篇,都是基于IOC容器来,思想和AOP差不多。

以上就是本章的全部内容了。

上一篇:Spring源码分析第二弹 - DI 依赖注入分析 下一篇:Spring源码分析第四弹 - MVC分析

莫等闲,白了少年头,空悲切