Spring之AOP源码阅读

338 阅读6分钟

前言

继上篇《Spring之AOP-先导篇》,我们对Spring AOP有了一个全面的初步了解之后,本篇我们将从源码级别解决上篇剩余的问题。

  • @EnableAspectJAutoProxy
  • Spring AOP具体怎么实现的?
  • jdk代理一定比cglib代理慢吗?

Spring Transaction Management是Spring AOP切面很好的例子,在笔者的《Transaction Management源码阅读路径》也有提及。

使用的代码

《Transaction Management源码阅读路径》使用的代码差不多,使用mysql、mybatis-plus、spring-boot。

import lombok.SneakyThrows;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement
@MapperScan(basePackages = {"com.whf.spring.dao"})
public class Application {
    @SneakyThrows
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

import com.whf.spring.service.business.TryService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
class ApplicationTests {
    @Autowired
    private TryService tryService;

    @Test
    void testTransaction() {
        tryService.test();
    }
}
import com.whf.spring.annotation.SimpleAnnotation;
import com.whf.spring.service.UserService;
import com.whf.spring.service.business.TryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Scope
@Slf4j
public class TryServiceImpl implements TryService {
    @Autowired
    private UserService userService;

    @Override
    @SimpleAnnotation
    @Transactional(rollbackFor = Exception.class)
    public void test() {
        log.info("执行业务");
        userService.test();
    }
}
import com.whf.spring.dao.UserDao;
import com.whf.spring.entity.UserDo;
import com.whf.spring.service.UserService;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserDo> implements UserService {
    @Override
    public void test() {
        this.selectById(1);
        throw new RuntimeException();
    }
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleAnnotation {
}
import com.whf.spring.annotation.SimpleAnnotation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Slf4j
@Component
public class SimpleAspect {
    @Around("@annotation(simpleAnnotation)")
    @SneakyThrows
    public Object simpleAround(ProceedingJoinPoint pjp, SimpleAnnotation simpleAnnotation) {
        log.info("进入simpleAround");
        Object proceed = pjp.proceed();
        return proceed;
    }
}

@EnableAspectJAutoProxy

《Spring之AOP-先导篇》中有提到启用@AspectJ支持可以在java配置类上加上@EnableAspectJAutoProxy注解。下面我们来了解下。

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

   /**
    * 指示是否创建基于子类(CGLIB)的代理,而不是基于标准Java接口的代理。默认值为false。
    */
   boolean proxyTargetClass() default false;

   /**
    * 指示AOP框架应将代理公开为ThreadLocal,以便通过org.springframework.aop.framework.AopContext进行检索。
    * 默认情况下关闭,即不保证AopContexr访问将正常工作。
    * @since 4.3.1
    */
   boolean exposeProxy() default false;

}

AspectJAutoProxyRegistrar

根据给定的@EnableAspectJAutoProxy注解,根据当前BeanDefinitionRegistry注册AnnotationAwareAspectJAutoProxyCreator

  • 可以看到使用的代码中没有显示使用@EnableAspectJAutoProxy,所以AnnotationMetadata的className为org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration很明显是spring boot的自动装配。BeanDefinitionRegistryDefaultListableBeanFactory
  • 注册的APC为AnnotationAwareAspectJAutoProxyCreator并且proxyTargetClass=true
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   /**
    * 根据在@Configuration类上的@EnableAspectJAutoProxy.proxyTargetClass() 属性值注册、升级、配置AspectJ APC(auto proxy creator)。
    */
   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

// 这里注册的是AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

      AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      if (enableAspectJAutoProxy != null) {
         // 这里为true,自动装配CglibAutoProxyConfiguration中指定的
         if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
// AnnotationAwareAspectJAutoProxyCreator#proxyTargetClass=true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         }
         //这里为false
         if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
         }
      }
   }

}

Spring AOP具体怎么实现的?

时序图

从注册APC到生成代理类并创建代理实例的时序图如下:

aop创建代理时序图.drawio.png

下面我们简单描述下步骤:

  1. 我们从AbstractApplicationContext#refresh方法的 invokeBeanFactoryPostProcessors(beanFactory);开始,调用bean工厂后处理器,从这里进入会调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());进而对APC进行注册。

  2. 进入AspectJAutoProxyRegistrar#registerBeanDefinitions进行对APC的注册,这里注册的APC为AnnotationAwareAspectJAutoProxyCreator。至于为啥会进入这里前面的“@EnableAspectJAutoProxy章节”已经提到了。注意这里自动装配的proxyTargetClasstrue

  3. bean工厂后处理器已经调用完成,下面我们的关注点就是被代理的bean进行实例化(包括生成代理类和创建代理实例)了,所以进入AbstractApplicationContext#finishBeanFactoryInitialization(beanFactory);完成对非懒初始化的单例进行实例化。

  4. 进入DefaultListableBeanFactory#preInstantiateSingletons进行实例化。

  5. 进入AbstractAutoProxyCreator实现类为AnnotationAwareAspectJAutoProxyCreator是一种BeanPostProcessor对bean实例化后期进行处理,这里调用postProcessAfterInitialization方法,如果bean被子类定义作为一个代理,使用一个被配置的interceptor创建代理。

  6. 进入AbstractAutoProxyCreatorwrapIfNecessary,如果需要包装被给的bean,例如,如果它是合适被代理。可以有多个specificInterceptor行成链式代理,这里包含了 {BeanFactoryTransactionAttributeSourceAdvisor ,InstantiationModelAwarePointcutAdvisor,DefaultPointcutAdvisor}。(这里说下DefaultPointcutAdvisor,DefaultPointcutAdvisor的Advice是ExposeInvocationInterceptor类,作用是在调用代理对象方法时,将相关信息存入ThreadLocal,以在多个advisor间进行传递。)

  7. 调用AopUtils#canApply,判断发现的advisors是否能被应用,返回false的话该advisor就不加入eligibleAdvisors,targetClass就不会被该advisor代理。

  8. 返回AbstractAutoProxyCreator#wrapIfNecessary,进行找到了所有能使用的advisors。下面要准备进行代理了。

  9. 调用DefaultAopProxyFactory#createAopProxy,根据被给的AOP配置创建AopProxy。这里使用了cglib来生成代理。

  10. 调用CglibAopProxy#getProxy,生成具体代理。

  11. 返回至AbstractAutoProxyCreatorwrapIfNecessary,已经代理实例已经创建好了,返回之后注入。

以上就是一个单例bean从注册APC到生成代理类并创建代理实例的大致步骤,核心类为AspectJAutoProxyRegistrarAbstractAutoProxyCreatorDefaultAopProxyFactoryCglibAopProxy,都有在子章节中详细的介绍。

AbstractAutoProxyCreator

{@link org.springframework.beans.factory.config.BeanPostProcessor}实现使用AOP代理包装合适的bean,在调用bean本身之前委托给特定的拦截器。

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
      implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

   /**
    * 子类的方便常量:不需要代理的返回值。
    * @see #getAdvicesAndAdvisorsForBean
    */
   @Nullable
   protected static final Object[] DO_NOT_PROXY = null;

   /**
    * Convenience constant for subclasses: Return value for
    * "proxy without additional interceptors, just the common ones".
    * 子类的方便常量:返回没有额外的拦截器只有普通的拦截器的返回值。
    * @see #getAdvicesAndAdvisorsForBean
    */
   protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];


   /** Logger available to subclasses. */
   protected final Log logger = LogFactory.getLog(getClass());

   /** Default is global AdvisorAdapterRegistry. */
   private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

   /**
    * 指示是否应冻结代理。重写父类以防止配置过早冻结。
    */
   private boolean freezeProxy = false;

   /** 默认没有公共拦截器 */
   private String[] interceptorNames = new String[0];

   private boolean applyCommonInterceptorsFirst = true;

   @Nullable
   private TargetSourceCreator[] customTargetSourceCreators;

   @Nullable
   private BeanFactory beanFactory;

   private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

   private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
   /** 代理类 **/
   private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
   /** 被建议的beans false表示advise bean **/
   private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
}   

wrapIfNecessary

如果需要包装被给的bean,例如,如果它是合适被代理。

这里的bean为TryServiceImpl

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;
   }

   // 创建代理如果有advice
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
      //把需要代理的bean进行put value为true
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 根据得到的specificInterceptors生成代理
      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;
}

DefaultAopProxyFactory

默认AopProxyFactory的实现,创建CGLIB代理或者JDK动态代理。

这里前面有提到config.isProxyTargetClass()为true。切面注解使用在类上所以会选择cglib代理。

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {


   @Override
   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)) {
            return new JdkDynamicAopProxy(config);
         }
         return new ObjenesisCglibAopProxy(config);
      }
      else {
         return new JdkDynamicAopProxy(config);
      }
   }

   /**
    * 确定提供的AdvisedSupport是否只指定了SpringProxy接口(或者根本没有指定代理接口)。
    */
   private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
      Class<?>[] ifcs = config.getProxiedInterfaces();
      return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
   }

}

CglibAopProxy

Spring AOP框架的基于CGLIB的AopProxy实现。这种类型的对象应该通过代理工厂获得,代理工厂由AdvisedSupport对象配置。这个类是Spring的AOP框架内部的,客户端代码不需要直接使用它。DefaultAopProxyFactory将在必要时自动创建基于CGLIB的代理,例如代理目标类(有关详细信息,请参阅attendant javadoc)。如果底层(目标)类是线程安全的,那么使用该类创建的代理是线程安全的。

class CglibAopProxy implements AopProxy, Serializable {

   // CGLIB索引数组索引常量。
   private static final int AOP_PROXY = 0;
   private static final int INVOKE_TARGET = 1;
   private static final int NO_OVERRIDE = 2;
   private static final int DISPATCH_TARGET = 3;
   private static final int DISPATCH_ADVISED = 4;
   private static final int INVOKE_EQUALS = 5;
   private static final int INVOKE_HASHCODE = 6;


   /** Logger available to subclasses; static to optimize serialization. */
   protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);

   /** 跟踪我们为fianl methods验证的类。*/
   private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();


   /** 用于配置此代理的配置*/
   protected final AdvisedSupport advised;

   @Nullable
   protected Object[] constructorArgs;

   @Nullable
   protected Class<?>[] constructorArgTypes;

   /** 在Advised方法上使用的Dispatcher */
   private final transient AdvisedDispatcher advisedDispatcher;

   private transient Map<Method, Integer> fixedInterceptorMap = Collections.emptyMap();

   private transient int fixedInterceptorOffset;


   public CglibAopProxy(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;
      this.advisedDispatcher = new AdvisedDispatcher(this.advised);
   }
}

getProxy

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
   }

   try {
      // 这里为TryServiceImpl
      Class<?> rootClass = this.advised.getTargetClass();
      Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

      // 代理的父类
      Class<?> proxySuperClass = rootClass;
      // 查看代理类名称是否包含cglib类分隔符
      if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
         proxySuperClass = rootClass.getSuperclass();
         Class<?>[] additionalInterfaces = rootClass.getInterfaces();
         for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
         }
      }

      // 验证类,根据需要编写日志信息。
      validateClassIfNecessary(proxySuperClass, classLoader);

      // 配置 CGLIB Enhancer...
      Enhancer enhancer = createEnhancer();
      if (classLoader != null) {
         enhancer.setClassLoader(classLoader);
         if (classLoader instanceof SmartClassLoader &&
               ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
         }
      }
      enhancer.setSuperclass(proxySuperClass);
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int x = 0; x < types.length; x++) {
         types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // 生成代理类并创建代理实例。callbacks就是被代理的方法拦截时会被执行的逻辑。
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (CodeGenerationException | IllegalArgumentException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
            ": Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (Throwable ex) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

jdk代理一定比cglib代理慢吗?

移步《静态代理、动态代理、cglib代理》