前言

  开启AOP性能后,AOP的逻辑是如何开始进行的。

一、Bean的生命周期

  要讲AOP就必须理解Spring Bean的生命周期,AOP的逻辑是在Bean初始化后这个阶段开始的。Spring Bean的生命周期简略上图:
 

二、AOP

(一)@EnableAspectJAutoProxy

  Spring中应用该注解开启AOP性能。该注解会注册一个AutoProxyCreatorAnnotationAwareAspectJAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator】相干的类到IOC容器中,AutoProxyCreator相干的类实现了InstantiationAwareBeanPostProcessor接口,即在Bean实例化前后会执行AOP的一些前置筹备操作。

  • 其中AbstractAutoProxyCreator实现了BeanFactoryAware接口,是咱们事务和aop导入进来的后置处理器的顶级父类;
  • AbstractAutoProxyCreator postProcessBeforeInstantiation实例化前办法中,会进行AOP切面Bean的缓存(是AdvicePointCutAdvisor根底Bean类型就间接跳过不解析);
     

    /**  AbstractAutoProxyCreator   * 在咱们的创立Bean的流程中还没调用结构器来实例化bean的时候进行调用(实例化前后)   * 咱们的aop 解析切面 以及事务解析事务注解都是在这里实现的   * @param beanClass 以后正在创立的bean的class对象   * @param beanName beanName   * @return   * @throws BeansException   */  @Override  public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {      //构建咱们的缓存key      Object cacheKey = getCacheKey(beanClass, beanName);      if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {          //如果被解析过 间接返回          if (this.advisedBeans.containsKey(cacheKey)) {              return null;          }          /**           * 判断是不是根底的bean           * 判断是不是应该跳过 (aop解析间接解析出咱们的切面信息(并且把咱们的切面信息进行保留),而事务在这里是不会解析的)           */          if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {              this.advisedBeans.put(cacheKey, Boolean.FALSE);              return null;          }      }      /**       * 这个中央个别是不会生成代理对象的,除非咱们的容器中有TargetSourceCreator 并且咱们的bean须要实现       * TargetSource接口       */      TargetSource targetSource = getCustomTargetSource(beanClass, beanName);      if (targetSource != null) {          if (StringUtils.hasLength(beanName)) {              this.targetSourcedBeans.add(beanName);          }          Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);          Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);          this.proxyTypes.put(cacheKey, proxy.getClass());          return proxy;      }      return null;  }

    (二)创立Proxy代理对象

  • AbstractAutoProxyCreator postProcessAfterInitialization初始化后办法中【每个Bean在创立的时候都会调用】,会进行AOP代理对象的创立,次要办法:wrapIfNecessary
     

    /**  AbstractAutoProxyCreator   * 在该后置办法中,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);          if (this.earlyProxyReferences.remove(cacheKey) != bean) {              //找到适合的就会被代理              return wrapIfNecessary(bean, beanName, cacheKey);          }      }      return bean;  }

    wrapIfNecessary办法如下:
     

    /**  AbstractAutoProxyCreator wrapIfNecessary   * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.   * @param bean the raw bean instance   * @param beanName the name of the bean   * @param cacheKey the cache key for metadata access   * @return a proxy wrapping the bean, or the raw bean instance as-is   */  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;      }      //是不是根底的bean 是不是须要跳过的      if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {          this.advisedBeans.put(cacheKey, Boolean.FALSE);          return bean;      }      //如果咱们有告诉的话,就创立代理对象      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;      }      this.advisedBeans.put(cacheKey, Boolean.FALSE);      return bean;  }
  • 创立代理的外围办法:createProxy(基于ProxyFactory)。其中真正的创立代理对象的办法是ProxyFactory.getProxy办法;
     

    /**     * Create a new proxy according to the settings in this factory.   * <p>Can be called repeatedly. Effect will vary if we've added   * or removed interfaces. Can add and remove interceptors.   * <p>Uses the given class loader (if necessary for proxy creation).   * @param classLoader the class loader to create the proxy with   * (or {@code null} for the low-level proxy facility's default)   * @return the proxy object   */  public Object getProxy(@Nullable ClassLoader classLoader) {      //createAopProxy() 用来获取咱们的代理工厂      return createAopProxy().getProxy(classLoader);  }

    createAopProxy办法会判断应用JDK动静代理还是CGLIB
     

    • CGLIB代理形式在第一次执行AOP操作的时候可能耗时会比拟长,因为须要生成新的字节码文件;
    • 总的状况,CGLIBJDK的形式性能都差不多;然而相比应用原生的AspectJ,性能还是要差上一些。AspectJ是基于字节码编制技术,不借助于Proxy对象实现。
       
    /**   * 实现类DefaultAopProxyFactory createAopProxy   * @param config 用来为咱们指定咱们advisor信息   * 该办法用来创立咱们的代理对象   * 所咱们的targetClass对象实现了接口,且  ProxyTargetClass 没有指定强制的走cglib代理,那么就是创立jdk代理   * 咱们代理的类没有实现接口,那么会间接走cglib代理   * 若咱们   ProxyTargetClass 指定为false 且代理类是接口才会走jdk代理 否在咱们还是cglib代理   * @return   * @throws AopConfigException   */  @Override  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {      //判断咱们是否前置指定应用cglib代理ProxyTargetClass =true  fasle      if (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.");          }          //所targetClass是接口 应用的就是jdk代理          if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {              return new JdkDynamicAopProxy(config);          }          //cglib代理          return new ObjenesisCglibAopProxy(config);      }      else {          //动静代理          return new JdkDynamicAopProxy(config);      }  }
    // 实现类JdkDynamicAopProxy getProxy办法@Override  public Object getProxy(@Nullable ClassLoader classLoader) {      if (logger.isDebugEnabled()) {          logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());      }      Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);      findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);      return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  }  /**   * Finds any {@link #equals} or {@link #hashCode} method that may be defined   * on the supplied set of interfaces.   * @param proxiedInterfaces the interfaces to introspect   */  private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {      for (Class<?> proxiedInterface : proxiedInterfaces) {          Method[] methods = proxiedInterface.getDeclaredMethods();          for (Method method : methods) {              if (AopUtils.isEqualsMethod(method)) {                  this.equalsDefined = true;              }              if (AopUtils.isHashCodeMethod(method)) {                  this.hashCodeDefined = true;              }              if (this.equalsDefined && this.hashCodeDefined) {                  return;              }          }      }  }

    创立完的代理对象就会保留到DefaultSingletonBeanRegistry的单例池singletonObjects中,之后getBean()获取到的就是这个单例池中的代理对象。


  后续思考针对AOP的一些优化措施,特地是盘绕告诉,在遇到所有AOP的性能瓶颈点的时候根本都是盘绕告诉。