Spring AOP源码分析

Spring的AOP

本文是在SpringBoot这层壳的基础之上讲解的AOP不在是老套的基于xml配置的那个年代讲解了。

我们带着疑问来开头!

  • 在Spring创建bean的过程中Aop是从哪个地方接入的
  • Aspect标注的切面类的方法是如何被映射成Advisor
  • 这些切面类的方法是如何应用到被代理的类上的即生成代理过程
  • 这些Advisor是如何变成代理类的MethodInterceptor或者handlerInterceptor的拦截方法的逻辑的
  • 调用目标类的方法时候切面类的切面逻辑及Advisor(@After @Before)方法是如何先执行、后执行 抛异常执行的

如果对这些问题你不太清楚,或者很想了解,那么这篇文章很适合你!

PS:对Spring的自动配置不清楚的可以参考下

配置类AopAutoConfiguration

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
      AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

   @Configuration
   @EnableAspectJAutoProxy(proxyTargetClass = false)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
   public static class JdkDynamicAutoProxyConfiguration {

   }

   @Configuration
   @EnableAspectJAutoProxy(proxyTargetClass = true)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
   public static class CglibAutoProxyConfiguration {

   }

}

可以禁用Aop 通过spring.aop.auto=false

默认使用的就是 CglibAutoProxyConfiguration 所以EnableAspectJAutoProxy的proxyTargetClass为true

通过设置spring.aop.proxy-target-class=false 可以选择为JDK的AOp代理方式

EnableAspectJAutoProxy注解

@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}
    */
   boolean exposeProxy() default false;

}

导入类AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar{
    
    
    @Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//①注册4A
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                //② 由之前的分析proxyTargetClass=true因此进入该出
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}


public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
		}
	}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,Object source) {

   return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    
		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

该类的继承关系如下: 它是一个BeanPostProcessor以及两个子类的

  • InstanitationAwareBeanPostProcessor
  • SamrtInstantiationAwareBeanPostProcessor

他们的一些方法入postProcessAfterInstantiation等都是一个bean创建的非常后置的流程哈哈!

AOP切入点

在这里插入图片描述

AbstractAutoProxyCreator#postProcessAfterInitialization#wrapIfNecessory就是Aop在bean创建过程中的切入点。

AOP的4A=AnnotationAwareAspectJAutoProxyCreator

之前分析Bean创建的整个过程在:拓展接口BeanPostProcessor的相关子类等

AbstractAutoProxyCreator#postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}
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;
   }

   //① 为当前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;
}

上面两个关键的方法:

  • #getAdvicesAndAdvisorsForBean
    • 满足当前类是需要被代理的,怎么才能满足被代理条件
    • 代理的逻辑
  • #createProxy
获取Bean通知器

getAdvicesAndAdvisorsForBean

AbstractAdvisorAutoProxyCreator#getAdviceAndAdvisorForBean

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);//② 获取能应用到该Bean的通知器
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}å
ReflectiveAspectJAdvisorFactory

ReflectiveAspectJAdvisorFactory

我们切面类中的注解都是在这里的到使用在AspectJAnnotationType枚举类存储

@Aspect

@Around

@Before

@After

@AfterReturning

@AfterThrowing

@Pointcut

它是专门处理切面类的跟你写的切面类密切相关,比如判断一个Bean是不是切面,

切面的@Before @After等方法标注的类包装成Advisor,以便于将通知逻辑加入到被拦截的方法上
在这里插入图片描述

BeanFactoryAspectJAdvisorsBuilderAdapter

在这里插入图片描述

此时正式我们正式从创建bean的流程中跳出来,为bean查找Advisor的时候,进入到从切面类获取通知器这些信息委托给了两个重要的类BeanFactoryAspectJAdvisorsBuilderAdapter和真正干活的ReflectiveAspectJAdvisorFactory类了。

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

   if (aspectNames == null) {
      synchronized (this) {
         aspectNames = this.aspectBeanNames;
         if (aspectNames == null) {
            List<Advisor> advisors = new LinkedList<>();
            aspectNames = new LinkedList<>();
            //① 从beanFactory获取所有的Object子类的bean
            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);
               if (beanType == null) {
                  continue;
               }
               if (this.advisorFactory.isAspect(beanType)) {//② 判断该Bean是否是Aspect
                  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 LinkedList<>();
   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;
}

方法看起来稍微有点长但是逻辑非常简单,而且大部分逻辑是放入到了ReflectiveAspectJAdvisorFactory中:

  • 从BeanFactory中获取Object的bean
  • 通过ReflectiveAspectJAdvisorFactory#isAspect判断bean是否有Aspect注解
  • 通过ReflectiveAspectJAdvisorFactory#getAdvisors获取Aspect类的通知器
  • 将获取到的Advisor缓存到BeanFactoryAspectJAdvisorsBuilderAdapter成员,以便于其它的bean创建的查找更快
通知器工厂类反射切面

反射获取切面类的通知器

反射获取切面类通知方法

其中的③List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

对象advisorFactory即ReflectiveAspectJAdvisorFactory

参数factory即BeanFactoryAspectInstanceFactory用来实例化切面类的–本质还是调用的beanFactory#getBean方法

在这里插入图片描述

PS: 既然Spring容器能创建@Aspect和@Component标注的类,为什么这里还要有一个@Aspect标注的类创建工厂BeanFactoryAspectInstanceFactory,而且还是调用Spring容器创建bean的方式来创建的

答案:就是创建@Aspect标注类的时机问题

比如启动阶段,切面类没有实例化的时候,有些方法被切面拦截,但是切面类没有初始化,那么执行拦截逻辑的时候就可以使用这个工厂调用SpringBean创建的方法,提前将切面类来实例化了。

ReflectiveAspectJAdvisorFactory#getAdvisors
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
   String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
   validate(aspectClass);
   MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

   List<Advisor> advisors = new LinkedList<>();
   for (Method method : getAdvisorMethods(aspectClass)) {
      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
      if (advisor != null) {
         advisors.add(advisor);
      }
   }
	//有删减
   return advisors;
}

步骤很简单:

  • A)获取@Aspect标注的切面类中所有的通知类型方法

  • B)将通知类型的方法包装成Advisor

A)的实现如下

排除@Pointcut标注的有注解的方法

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new LinkedList<>();
    ReflectionUtils.doWithMethods(aspectClass, method -> {
        // Exclude pointcuts
        if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
        }
    });
    methods.sort(METHOD_COMPARATOR);
    return methods;
}

B)的实现如下

将@Aspect切面类实例化工厂、 通知方法、 切面类名字传入

方法将切入点@execution(那个包那些方法)解析出来

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
      int declarationOrderInAspect, String aspectName) {

   validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

   AspectJExpressionPointcut expressionPointcut = getPointcut(
         candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
   if (expressionPointcut == null) {
      return null;
   }

   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
  • 最后创建的Advisor中信息已近很全了

  • 切点 @execution表达式拦截的包方法等

  • 通知器(切面逻辑)method

  • 切面类创建工厂类

  • 切面名字
    在这里插入图片描述

切面中的每个@Before/@After等注解标注的方法在此时都会变成Advisor 并且放入到了BeanFactoryAspectJAdvisorBuilder的成员中了,获取bean通知器的逻辑至此结束!!!

获取能应用到该Bean的通知器

主要是通过一个AopUtils类来判断这个通知能否应用到该类上面, 判断依据就是从@After @Before上面解析出来的Pointcut表达式是否匹配当前的类。

AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);

创建Bean代理类

整个父类AbstractAdvisorAutoProxyCreator#wrapIfNecessary#createProxy的方法

Object proxy = createProxy(
      bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
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());
}

先插入一点ProxyFactory相关的补充逻辑在这里插入图片描述

public class ProxyCreatorSupport extends AdvisedSupport {

   private AopProxyFactory aopProxyFactory;
    
   public ProxyCreatorSupport() {
       this.aopProxyFactory = new DefaultAopProxyFactory();
   }
}


public class AdvisedSupport extends ProxyConfig implements Advised {
		private List<Advisor> advisors = new LinkedList<>();
}

里边的有两个重要的成员:AopProxyFactory和List< Advisor>

AopProxyFactory工厂

该工厂用于创建代理AopProxy,主要使用过AOP配置选择使用哪个AopProxy

如java自带的jdk动态代理和cglib的动态代理

有了这个AopProxy就可以为目标类创建代理了!

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
   //方法的参数config就是ProxyFactory自己
   @Override
   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代理 主要的就是实现Invocationhandler

    • 创建代理Proxy.Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  • CGLB代理 主要是Enhancer类,要实现MethodInterceptor接口

    • 创建代理Enchancer.setCallback
    • enchancer.create()或者enchancer.createClass

选择的条件就是:这里的判断条件

比如你指定制定了属性 proxyTargetClass=true 并且不是被代理对象不是接口类型的则使用Cglib代理

这个属性的配置就是:注解类EnableAspectJAutoProxy的属性

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

}

如何配置?

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
      AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

   @Configuration
   @EnableAspectJAutoProxy(proxyTargetClass = false)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
   public static class JdkDynamicAutoProxyConfiguration {

   }

   @Configuration
   @EnableAspectJAutoProxy(proxyTargetClass = true)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
   public static class CglibAutoProxyConfiguration {

   }

}

那么就很简单了吧使用spring.aop.proxy-target-class这个属性就可以指定了true和false

CGLB方式创建代理

再回到前面的proxyFactory.getProxy(getProxyClassLoader());即为bean创建代理

ObjenesisCglibAopProxy(ProxyFactory)即方法CglibAopProxy#getProxy的逻辑

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
  
   try {
      Class<?> rootClass = this.advised.getTargetClass();
      proxySuperClass = rootClass.getSuperclass();

	  //内容有删减
      Enhancer enhancer = createEnhancer();
      enhancer.setSuperclass(proxySuperClass);//目标类
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

      Callback[] callbacks = getCallbacks(rootClass);//callback
      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);

      // Generate the proxy class and create a proxy instance.
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (Throwable ex) {
     
   }
}

排除掉一些无用的代码 逻辑看起来清晰了一些。跟我们自己创建Cglib代理差别不大。

我只需要知道,被代理的目标类,实现了那个接口,有哪些callback就ok

设置目标类要宣称实现的接口

被代理目标类宣称实现了哪些接口

AopProxyUtils.completeProxiedInterfaces(this.advised)

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
   Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
   if (specifiedInterfaces.length == 0) {
      // No user-specified interfaces: check whether target class is an interface.
      Class<?> targetClass = advised.getTargetClass();
      if (targetClass != null) {
         if (targetClass.isInterface()) {
            advised.setInterfaces(targetClass);
         }
         else if (Proxy.isProxyClass(targetClass)) {
            advised.setInterfaces(targetClass.getInterfaces());
         }
         specifiedInterfaces = advised.getProxiedInterfaces();
      }
   }
   boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
   boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
   boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
   int nonUserIfcCount = 0;
   if (addSpringProxy) {
      nonUserIfcCount++;
   }
   if (addAdvised) {
      nonUserIfcCount++;
   }
   if (addDecoratingProxy) {
      nonUserIfcCount++;
   }
   Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
   System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
   int index = specifiedInterfaces.length;
   if (addSpringProxy) {
      proxiedInterfaces[index] = SpringProxy.class;
      index++;
   }
   if (addAdvised) {
      proxiedInterfaces[index] = Advised.class;
      index++;
   }
   if (addDecoratingProxy) {
      proxiedInterfaces[index] = DecoratingProxy.class;
   }
   return proxiedInterfaces;
}
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));

这三行代码被代理类(目标类)

以第一行为例没有实现接口SpringProxy 就需要这里就宣称被代理类会实现这个接口

总之就是被创建出来的代理类会宣称实现了SpringProxy和Advised接口的

SpringProxy和Advisor这两个接口连同目标类自己实现的接口 就是创建出的代理类实现的接口

设置目标类的回调

Callback[] callbacks = getCallbacks(rootClass);

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
   // Parameters used for optimization choices...
   boolean exposeProxy = this.advised.isExposeProxy();
   boolean isFrozen = this.advised.isFrozen();
   boolean isStatic = this.advised.getTargetSource().isStatic();

   // Choose an "aop" interceptor (used for AOP calls).
   Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

   // Choose a "straight to target" interceptor. (used for calls that are
   // unadvised but can return this). May be required to expose the proxy.
   Callback targetInterceptor;
   if (exposeProxy) {
      targetInterceptor = isStatic ?
            new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
   }
   else {
      targetInterceptor = isStatic ?
            new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
   }

   // Choose a "direct to target" dispatcher (used for
   // unadvised calls to static targets that cannot return this).
   Callback targetDispatcher = isStatic ?
         new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();

   Callback[] mainCallbacks = new Callback[] {
         aopInterceptor,  // for normal advice
         targetInterceptor,  // invoke target without considering advice, if optimized
         new SerializableNoOp(),  // no override for methods mapped to this
         targetDispatcher, this.advisedDispatcher,
         new EqualsInterceptor(this.advised),
         new HashCodeInterceptor(this.advised)
   };

   Callback[] callbacks;

   // If the target is a static one and the advice chain is frozen,
   // then we can make some optimizations by sending the AOP calls
   // direct to the target using the fixed chain for that method.
   if (isStatic && isFrozen) {
      Method[] methods = rootClass.getMethods();
      Callback[] fixedCallbacks = new Callback[methods.length];
      this.fixedInterceptorMap = new HashMap<>(methods.length);

      // TODO: small memory optimization here (can skip creation for methods with no advice)
      for (int x = 0; x < methods.length; x++) {
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
         fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
               chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
         this.fixedInterceptorMap.put(methods[x].toString(), x);
      }

      // Now copy both the callbacks from mainCallbacks
      // and fixedCallbacks into the callbacks array.
      callbacks = new Callback[
          .length + fixedCallbacks.length];
      System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
      System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
      this.fixedInterceptorOffset = mainCallbacks.length;
   }
   else {
      callbacks = mainCallbacks;
   }
   return callbacks;
}

除了几个固定的Interceptor之外还添加了另外的两个MethodInterceptor

  • DynamicAdvisedInterceptor
  • StaticDispatcher
Enchaner创建代理对象
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
   Class<?> proxyClass = enhancer.createClass();//①代理类就生成了
   
   Object proxyInstance = null;

   if (objenesis.isWorthTrying()) {
      try {
         proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());//②
      }
      catch (Throwable ex) {
         logger.debug("Unable to instantiate proxy using Objenesis, " +
               "falling back to regular proxy construction", ex);
      }
   }

   if (proxyInstance == null) {
      // Regular instantiation via default constructor...
      try {
         Constructor<?> ctor = (this.constructorArgs != null ?
               proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
               proxyClass.getDeclaredConstructor());
         ReflectionUtils.makeAccessible(ctor);
         proxyInstance = (this.constructorArgs != null ?
               ctor.newInstance(this.constructorArgs) : ctor.newInstance());
      }
      catch (Throwable ex) {
         throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
               "and regular proxy instantiation via default constructor fails as well", ex);
      }
   }

   ((Factory) proxyInstance).setCallbacks(callbacks);//③
   return proxyInstance;
}

①处的代理类就生成了

com.architecture.sharding.jdbc.service.UserService$ $ EnhancerBySpringCGLIB$ $4f1b14ca

两个$$的哦!

②就是实例化了这个这个代理类了

③就是设置callback了 就是上面的methodInterceptor

至此这个bean就创建出来了,返回的是我们的代理对象。

这次关于启动的部分终结。

DynamicAdvisedInterceptor运行拦截

前面说的都是启动过程生成代理的过程,那么在方法执行的时候如何执行的切面逻辑需要看MethodInterceptor了

它是CglibAopProxy的内部类,并且很显然的是MethodInterceptor

里边的advised属性就是ProxyFactory本身 包含适合于当前类的所有的Advisor

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

   private final AdvisedSupport advised;

   public DynamicAdvisedInterceptor(AdvisedSupport advised) {
      this.advised = advised;
   }

   @Override
   @Nullable
   public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
      Object oldProxy = null;
      boolean setProxyContext = false;
      Object target = null;
      TargetSource targetSource = this.advised.getTargetSource();
      try {
         if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
         }
        
         target = targetSource.getTarget();
         Class<?> targetClass = (target != null ? target.getClass() : null);
         //①从适合于该类的所有的通知找到适合该方法的通知器
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
         Object retVal;
         if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = methodProxy.invoke(target, argsToUse);
         }
         else {
            //② 将代理对象 目标类 方法参数  以及拦截逻辑链条chain  包装成方法执行对象
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
         }
         retVal = processReturnType(proxy, target, method, retVal);
         return retVal;
      }
      finally {
         if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
         }
         if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
         }
      }
   }

   @Override
   public boolean equals(Object other) {
      return (this == other ||
            (other instanceof DynamicAdvisedInterceptor &&
                  this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
   }

   /**
    * CGLIB uses this to drive proxy creation.
    */
   @Override
   public int hashCode() {
      return this.advised.hashCode();
   }
}

chain !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值