spring源码分析-aop原理

107 阅读3分钟

spring实现AOP思路:

1: 创建AnnotationAwareAspectJAutoProxyCreator对象
2: 扫描容器中的切面,创建PointcutAdvisor对象
3: 生成代理类

继承关系

image.png

  • AbstractAutoProxyCreator 创建代理对象
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      //advisedBeans用于存储不可代理的bean,如果包含直接返回
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }

      //判断当前bean是否可以被代理,然后存入advisedBeans
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   //获取封装当前bean的TargetSource对象,如果不存在,则直接退出当前方法,否则从TargetSource
   // 中获取当前bean对象,并且判断是否需要将切面逻辑应用在当前bean上。
   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;
}
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      //如果条件符合,则为bean生成代理对象
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}
/**
 * 1.  如果已经处理过,且该bean没有被代理过,则直接返回该bean
 *    2.如果该bean是内部基础设置类Class 或 配置了该bean不需要代理,则直接返回bean(返回前标记该bean已被处理过)
 *    3.获取所有适合该bean的增强Advisor
 *     如果增强不为null,则为该bean创建代理对象,并返回结果
 */
/**
 * 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) {
   //如果已经处理过(targetSourcedBeans存放已经增强过的bean)
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   //advisedBeans的key为cacheKey,value为boolean类型,表示是否进行过代理
   //已经处理过的bean,不需要再次进行处理,节省时间
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   //是否是内部基础设置类Class || 配置了指定bean不需要代理,如果是的话,直接缓存。
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // 获取当前对象所有适用的Advisor.加入当前对象是orderController,那么找到所有切点是他的对应的@Aspect注解的类
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

   //如果获取的增强不为null,则为该bean创建代理(DO_NOT_PROXY=null)
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      //创建代理对象时候会用到是否进行JDK代理或者CGLIB代理
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   //标记该cacheKey已经被处理过
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

/**
 * 如果一个bean继承自Advice、Pointcut、Advisor、AopInfrastructureBean 或者 
 * 带有@Aspect注解,或被Ajc(AspectJ编译器)编译都会被认定为内部基础设置类
 * Return whether the given bean class represents an infrastructure class
 * that should never be proxied.
 * <p>The default implementation considers Advices, Advisors and
 * AopInfrastructureBeans as infrastructure classes.
 * @param beanClass the class of the bean
 * @return whether the bean represents an infrastructure class
 * @see org.aopalliance.aop.Advice
 * @see org.springframework.aop.Advisor
 * @see org.springframework.aop.framework.AopInfrastructureBean
 * @see #shouldSkip
 */
protected boolean isInfrastructureClass(Class<?> beanClass) {
   boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
         Pointcut.class.isAssignableFrom(beanClass) ||
         Advisor.class.isAssignableFrom(beanClass) ||
         AopInfrastructureBean.class.isAssignableFrom(beanClass);
   if (retVal && logger.isTraceEnabled()) {
      logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
   }
   return retVal;
}
  • AnnotationAwareAspectJAutoProxyCreator

aopProxy 代理对象生成过程

image.png

jdkProxy cglibProxy 区别

image.png

  • 开启cglibProxy
proxyTargetClass=true