Spring框架AOP源码分析

Spring框架AOP源码分析

1.写在前面

做java开发的不可能不适用spring框架,我们都知道spring框架的两个基础功能就是Ioc和aop,相比来说Ioc会应用的更广泛一些,但aop同样重要,今天就来详细分析一下spring的aop的实现原理,会深入spring源码级别,对于spring不太熟悉的同学来说可能有点难,没有办法,分析源码就是这样,需要对框架有一定的应用经验并且比较熟悉原理,毕竟一个成熟的框架,特别是像spring这样的java技术栈统治级的框架。如果想学习spring的基本功能推荐几篇文章。

另外这篇源码分析也是干货满满。

好,我们开始今天的主题,首先搭建一个基本的spring环境,本案例是基于注解分析的。

2.环境搭建

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.6</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.6</version>
    </dependency>
</dependencies>

创建一个启动配置类,这是一个空配置类,仅仅为了启动加载。@EnableAspectJAutoProxy注解表示使能了基于AspectJ的AOP的功能

@Configuration
@ComponentScan(basePackages = {"com.li.study"})
@EnableAspectJAutoProxy
public class AppConfig {

}

创建两个bean,一个是普通的bean,另一个是用于AOP功能用于定义切点,通知的bean

@Component
public class CommonBean {

    public void test(){
        System.out.println("勤能补拙");
    }
}
@Component
@Aspect
public class AspectBean {

    @Pointcut("execution(* com.li.study.bean.CommonBean.*(..))")
    public void pointcut(){};


    @Before("pointcut()")
    public void before(){

        System.out.println("before");
    }

    @After("pointcut()")
    public void after(){

        System.out.println("after");
    }

    @Around("pointcut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint){

        System.out.println("xxxx");
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("oooo");

    }
}

最后创建一个启动类

public class TestBean {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        CommonBean bean = context.getBean(CommonBean.class);
        bean.test();
    }
}

最后启动main方法,执行结果如下

xxxx
before
勤能补拙
after
oooo

这就是一个简单的AOP测试案例,为了让大家熟悉AOP是什么,这里不太想说明具体什么是AOP,因为这个很难几句话说明白,大家可以对比面向对象来理解,这个叫面向切面,它是一种横向的扩展,总之只可意会不可言传,我相信你是理解AOP的,不然也不会看到这里,如果您不知道什么是AOP和OOP,那。。。慢走不送,出门左转。

3.源码分析

3.1 @EnableAspectJAutoProxy注解

在配置类上添加@EnableAspectJAutoProxy注解就打开了基于AspectJ的动态代理功能,那么为什么呢?怎么实现的呢?我们来看一下。

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

   /**
    * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    * to standard Java interface-based proxies. The default is {@code false}.
    */
   boolean proxyTargetClass() default false;

   /**
    * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
    * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
    * Off by default, i.e. no guarantees that {@code AopContext} access will work.
    * @since 4.3.1
    */
   boolean exposeProxy() default false;
}

我们看到这个注解上添加了一个@Import(AspectJAutoProxyRegistrar.class)注解,就是这个注解实现类基于AspectJ的动态代理功能,这个@Import注解很强大,

他可以将对象注入到Spring容器中,具体的实现原理请参考@Import注解详细分析,这里不详细分析了,这篇文章写的很清楚。我们直接进入AspectJAutoProxyRegistrar类。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   /**
    * Register, escalate, and configure the AspectJ auto proxy creator based on the value
    * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
    * {@code @Configuration} class.
    */
   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

      AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      if (enableAspectJAutoProxy != null) {
         if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         }
         if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
         }
      }
   }

}

这个类实现了ImportBeanDefinitionRegistrar接口,通过@Improt注解传入实现ImportBeanDefinitionRegistrar接口的类,在创建容器的时候会调用接口的registerBeanDefinitions方法,这是@Import注解的一种用法。

我们来看具体的方法实现,主要关注方法的第一行代码。从方法名上来看,是注册名字是AspectJAnnotationAutoProxyCreator的类的对象到容器中。

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
   return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
      Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
      BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
         int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
         int requiredPriority = findPriorityForClass(cls);
         if (currentPriority < requiredPriority) {
            apcDefinition.setBeanClassName(cls.getName());
         }
      }
      return null;
   }

   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

上面的代码实际上就是注册了一个类型为AnnotationAwareAspectJAutoProxyCreator的bean到容器中,其实这就是@EnableAspectJAutoProxy注解主要实现的功能。

3.2 AnnotationAwareAspectJAutoProxyCreator

先来看一下继承结构
在这里插入图片描述
通过上图可以看出,AnnotationAwareAspectJAutoProxyCreator间接实现类BeanPostProcessor接口,是一个后置处理器。spring的后置处理器的学习请移步BeanPostProcessor后置处理器原理与应用

既然是后置处理器我们主要关注BeanPostProcessor接口定义的方法。

public interface BeanPostProcessor {
   @Nullable
   default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }

   @Nullable
   default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      return bean;
   }
}

通过方法的名字也能看出来,这两个方法一个是在bean初始化前执行,一个是在初始化后执行。重写这两个方法的类是AbstractAutoProxyCreator,我们这两个方法的实现。

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
   return bean;
}

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);  //获取key,根据beanName是不是空以及是不是工厂bean来确定key
       
      //earlyProxyReferences集合不包含当前bean,成立,这个判断与在bean实例化之前被代理有关,要实现实例化之前被代理需要其他配置,
      //在本案例中没有配置,所以会执行到if语句内部代码
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {  
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

初始化之前执行的方法没做什么处理,我们关注初始化之后的逻辑。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   //beanName不是空并且在实例化时候已经被缓存到targetSourcedBeans,已经在是实例化是被代理
   //不需要实例化完成后处理了
   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.
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);  //查找当前bean的所有通知
   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;
}

3.3 查找增强

这里说的增强包括Advice和Advisor,查找的方法在AbstractAdvisorAutoProxyCreator类

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) {
   List<Advisor> candidateAdvisors = findCandidateAdvisors();  //查找所有增强
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

这里主要分为两个步骤:查找所有增强,在所有增强中找到匹配当前类型的

3.3.1 查找全部增强

注意这个查找所有增强的方法在AnnotationAwareAspectJAutoProxyCreator中,在这个方法中会调用父类的findCandidateAdvisors方法。

protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   if (this.aspectJAdvisorsBuilder != null) {
      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}
3.3.1.1 父类查找增强的方法

我们先去看一下父类的这个方法的实现,在AbstractAdvisorAutoProxyCreator类中

protected List<Advisor> findCandidateAdvisors() {
   Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
   return this.advisorRetrievalHelper.findAdvisorBeans();
}

继续向下看查找的方法实现

public List<Advisor> findAdvisorBeans() {
   // Determine list of advisor bean names, if not cached already.
   String[] advisorNames = this.cachedAdvisorBeanNames;
   if (advisorNames == null) {
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the auto-proxy creator apply to them!
      advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
      this.cachedAdvisorBeanNames = advisorNames;
   }
   if (advisorNames.length == 0) {
      return new ArrayList<>();
   }

   List<Advisor> advisors = new ArrayList<>();
   for (String name : advisorNames) {
      if (isEligibleBean(name)) {
         if (this.beanFactory.isCurrentlyInCreation(name)) {
            if (logger.isTraceEnabled()) {
               logger.trace("Skipping currently created advisor '" + name + "'");
            }
         }
         else {
            try {
               advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
            catch (BeanCreationException ex) {
               Throwable rootCause = ex.getMostSpecificCause();
               if (rootCause instanceof BeanCurrentlyInCreationException) {
                  BeanCreationException bce = (BeanCreationException) rootCause;
                  String bceBeanName = bce.getBeanName();
                  if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                     if (logger.isTraceEnabled()) {
                        logger.trace("Skipping advisor '" + name +
                              "' with dependency on currently created bean: " + ex.getMessage());
                     }
                     // Ignore: indicates a reference back to the bean we're trying to advise.
                     // We want to find advisors other than the currently created bean itself.
                     continue;
                  }
               }
               throw ex;
            }
         }
      }
   }
   return advisors;
}

这个方法逻辑比较清晰,都是一样的套路,先看有没有缓存,没有的话再去查找所有实现Advisor的beanName,然后将结果缓存起来,最后遍历beanName集合找到容器中的所有Advisor实现类,并返回。

3.3.1.2 当前类查找增强的方法

当前类中其实包含了解析AspectJ相关的注解的。

public List<Advisor> buildAspectJAdvisors() {
   List<String> aspectNames = this.aspectBeanNames;

   if (aspectNames == null) {
      synchronized (this) {
         aspectNames = this.aspectBeanNames;
         if (aspectNames == null) {
            List<Advisor> advisors = new ArrayList<>();
            aspectNames = new ArrayList<>();
            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                  this.beanFactory, Object.class, true, false);
            for (String beanName : beanNames) {
               if (!isEligibleBean(beanName)) {
                  continue;
               }
               // We must be careful not to instantiate beans eagerly as in this case they
               // would be cached by the Spring container but would not have been weaved.
               Class<?> beanType = this.beanFactory.getType(beanName, false);
               if (beanType == null) {
                  continue;
               }
               if (this.advisorFactory.isAspect(beanType)) {
                  aspectNames.add(beanName);
                  AspectMetadata amd = new AspectMetadata(beanType, beanName);
                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                     MetadataAwareAspectInstanceFactory factory =
                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                     List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);  //读取切点信息
                     if (this.beanFactory.isSingleton(beanName)) {
                        this.advisorsCache.put(beanName, classAdvisors);
                     }
                     else {
                        this.aspectFactoryCache.put(beanName, factory);
                     }
                     advisors.addAll(classAdvisors);
                  }
                  else {
                     // Per target or per this.
                     if (this.beanFactory.isSingleton(beanName)) {
                        throw new IllegalArgumentException("Bean with name '" + beanName +
                              "' is a singleton, but aspect instantiation model is not singleton");
                     }
                     MetadataAwareAspectInstanceFactory factory =
                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                     this.aspectFactoryCache.put(beanName, factory);
                     advisors.addAll(this.advisorFactory.getAdvisors(factory));
                  }
               }
            }
            this.aspectBeanNames = aspectNames;
            return advisors;
         }
      }
   }

   if (aspectNames.isEmpty()) {
      return Collections.emptyList();
   }
   List<Advisor> advisors = new ArrayList<>();
   for (String aspectName : aspectNames) {
      List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
      if (cachedAdvisors != null) {
         advisors.addAll(cachedAdvisors);
      }
      else {
         MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
         advisors.addAll(this.advisorFactory.getAdvisors(factory));
      }
   }
   return advisors;
}
  • 这个方法的前一部分实现类与父类中查找增强的逻辑,这里我没搞清楚为什么又查找一遍,明明已经在上面执行了父类相同的逻辑,希望明白其中原理的大佬指点,不胜感激
  • 接下来判断当前bean是否有@Aspect注解,如果存在的话会去解析@Pointcut注解,获取切点信息,然后根据是不是单例的将增强缓存到不同的集合中
  • 最后将获取的增强返回

至此,所有的增强已经获取完成并缓存,接下来开始找到匹配当前bean的增强

3.4 查找匹配的增强

我们回到AbstractAdvisorAutoProxyCreator类的findEligibleAdvisors方法的第二行代码继续分析。

protected List<Advisor> findAdvisorsThatCanApply(
      List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

第一行和最后一行做了一个正在代理的一个标记,我们看中间的代码

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List<Advisor> eligibleAdvisors = new ArrayList<>();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
         eligibleAdvisors.add(candidate);
      }
   }
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         // already processed
         continue;
      }
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}

这个方法先遍历所有的增强,如果是IntroductionAdvisor的实现类,并且可以应用到当前的bean,加入到结合。

IntroductionAdvisor是Advisor的子接口,增加了过滤和验证的方法,主要作用还是Advisor。我们来看匹配增强的方法canApply

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
   return canApply(advisor, targetClass, false);
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
   if (advisor instanceof IntroductionAdvisor) {
      return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
   }
   else if (advisor instanceof PointcutAdvisor) {
      PointcutAdvisor pca = (PointcutAdvisor) advisor;
      return canApply(pca.getPointcut(), targetClass, hasIntroductions);
   }
   else {
      // It doesn't have a pointcut so we assume it applies.
      return true;
   }
}

这里显示判断IntroductionAdvisor接口,然后执行过滤,然后继续执行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));
   }
   
   //获取当前bean的所有包括子类的方法对象,注意这里有些误导,不只是获取了接口方法对象
   classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

   for (Class<?> clazz : classes) {
      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
      for (Method method : methods) {
         //查找匹配的方法,通过AspectJ的表达式来匹配的
         if (introductionAwareMethodMatcher != null ?
               introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
               methodMatcher.matches(method, targetClass)) {
            return true;
         }
      }
   }

   return false;
}

上面的代码写了注释,先做一些判断,如果匹配所有的增强就不向下执行了,已经是代理对象的就不再匹配了,然后获取当前类及其子类的所有方法对象,这里是所有方法不只是接口方法,遍历执行匹配逻辑。

到目前位置获取了所有匹配的增强,接下来就是执行更具增强执行代理逻辑了。

3.5 创建代理对象

我们回到查找增强的方法的下面继续阅读,位置在AbstractAutoProxyCreator类的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.
   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;
}

我们来看Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

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);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }

   return proxyFactory.getProxy(getProxyClassLoader());
}

这个方法一个重要的事情是创建了一个代理工厂类,然后将增强集合以及目标代理类保存到代理工厂中。真正创建代理对象的再左后一行代码。我们进入代理工厂的getProxy方法。

public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}

这个他先创建一个AopProxy对象,我们看一下实现逻辑。

protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
      activate();
   }
   return getAopProxyFactory().createAopProxy(this);
}

这里他先获取了AopProxy的工厂,这个AopProxy工厂实际的实现类是DefaultAopProxyFactory。接下来就是去这个工厂获取AopProxy对象。

3.5.1 通过工厂方法获取AopProxy对象

这个createAopProxy是AopProxyFactory的接口方法,DefaultAopProxyFactory实现了AopProxyFactory接口。

这里的思路不知道大家看出来没有,这是一个标准的工厂方法模式,通过接口获取对象,如果我们不想利用AopProxy对象来实现动态代理,可以自定义一个实现AopProxyFactory接口的类,提供自定义的AopProxy实现来完成相应的扩展。

来看DefaultAopProxyFactory实现的createAopProxy方法。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   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.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

这里的逻辑可能大家一看就觉得熟悉,这就是常说的JDK的动态代理和Cglib的动态代理两种方式。

如果目标对象实现了接口或者本身就是代理对象,那么使用JDK的动态代理,否则使用Cglib动态代理。

3.5.2 JDK动态代理

不管是JDK的动态代理还是Cglib动态代理都实现了AopProxy接口,我们先来看JDK动态代理的getProxy方法

public Object getProxy() {
   return getProxy(ClassUtils.getDefaultClassLoader());
}
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);
}

其实这里没什么可以多说的,就是JDK动态代理的原理,我们自己应用JDK的动态代理功能也是这样做的。

  • 先获取要代理的接口方法
  • 创建InvocationHandler接口实现对象
  • 创建代理对象

这里的JdkDynamicAopProxy类同时实现来InvocationHandler接口,创建代理对象时传入的是this,这里的细节跳过了。

3.5.3 Cglib动态代理

Cglib是一个常用的代码生成技术,在很多框架中都有应用,他是对字节码操作的,很底层,本人理解的不是很充分,这里也不误导大家了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值