从servlet到springboot(12) spring中aop的实现原理

56 篇文章 2 订阅

前面几节的大部分都集中在spring的IOC部分,我们都知道spring的两大核心除了IOC之外还有AOP。aop的实现底层是动态代理,那么spring是如果实现这种动态代理,来达到aop的效果呢,这一节我们将揭开。

 

由于我们是在springboot中分析的,所以我们依然在springboot框架下分析。

我们找到@EnableAspectJAutoProxy注解

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

注意到这里import了一个AspectJAutoProxyRegistrar.class。熟悉spring注解驱动的都知道,这里会运行AspectJAutoProxyRegistrar#registerBeanDefinitions方法。

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);这行代码进入

直接跳到AopConfigUtils#registerOrEscalateApcAsRequired

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    //忽略
    } else {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", -2147483648);
        beanDefinition.setRole(2);
        registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
        return beanDefinition;
    }
}

这里会在beanDefinitionMap中加入一个key是org.springframework.aop.config.internalAutoProxyCreator

value是AnnotationAwareAspectJAutoProxyCreator Definition的kv对

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

下面两步是把EnableAspectJAutoProxy注解中的proxyTargetClass和exposeProxy注解取来,如果是true,会做一些强制工作

下面我们要详细说AnnotationAwareAspectJAutoProxyCreator这个类,通过查看这个类的继承关系

注意到AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware 这里有一个SmartInstantiationAwareBeanPostProcessor和一个BeanFactoryaware我们之前也分析过BeanPostProcessor的作用,当然这里是SmartInstantiationAwareBeanPostProcessor,

先看BeanFactoryaware#setBeanFactory方法

这个方法在AbstractAdvisorAutoProxyCreator#setBeanFactory进行重写

public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
        throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    } else {
        this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
    }
}
AnnotationAwareAspectJAutoProxyCreator#initBeanFactory
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.initBeanFactory(beanFactory);
    if (this.aspectJAdvisorFactory == null) {
        this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
    }

    this.aspectJAdvisorsBuilder = new AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

这里做了两个动作,一个是创建aspectJ通知工厂,另一个动作是创建适配器

。接下去我们分析继承SmartInstantiationAwareBeanPostProcessor接口的原因

我们直接找到AbstractAutowireCapableBeanFactory的createBean方法,可以找到

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

还是那个面的注解就是返回一个代理对象。

aop的实际过程是在后置处理器的applyBeanPostProcessorsAfterInstantiation中

直接进入

AbstractAutoProxyCreator#applyBeanPostProcessorsAfterInstantiation
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }

    return bean;
}

this.wrapIfNecessary这句话是关键点击进入句句分析

Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null)

这里是获取到当前bean的所有增强器,也就是切面前后需要的方法,有一点值得主意的是都会有这个增强器

org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR,这些增强器会加入到一个集合中

如果specificInterceptors(增强器集合不为空)就会创建代理对象,
if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
}

我们进入createProxy

截取关键句分析

ProxyFactory proxyFactory = new ProxyFactory();这里创建一个代理工厂类,这个类是产生代理对象的关键
proxyFactory.addAdvisor(advisor); 这里把增强器的集合设置在proxyFactory中
proxyFactory.setTargetSource(targetSource) 把被增强的对象添加到工厂类中
return proxyFactory.getProxy(this.getProxyClassLoader());这句话是通过代理工厂来创建对象,我们进入这个方法
public Object getProxy(ClassLoader classLoader) {
    return this.createAopProxy().getProxy(classLoader);
}

这里createAopProxy有两个实现类,一个jdk的,一个是cglib的,两个区别在于,如果target对象是通过接口实现的,就通过jdk的实现类来创建代理对象,如果不是,则通过cglib的实现类来创建代理对象

贴上源代码

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

我们这里看JDK的动态代理

public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }

    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

最后一句话Proxy.newProxyInstance就创建了目标类的一个代理类

此时我们就得到了一个增强后的代理类,其中也包括了增强器

这时候在spring容器的bean其实就是增强的代理bean,

当调用这个bean方法时候,实际上是调用这个代理bean。我们执行bean方法时候,先会调用

JdkDynamicAopProxy#invoke 方法

进入这个方法我们慢慢分析关键语句

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

这句话将会获得所有增强类的集合

这里用到了一个适配器模式,因为传入的是一个通知,适配成interceptor 

MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

这里会创建一个MethodInvocation,然后执行它的proceed()方法

Override
public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
   }
。。。。。。。
   else {
      // It's an interceptor, so we just invoke it: The pointcut will have
      // been evaluated statically before this object was constructed.
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

这里有个递归的过程,((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);里面执行的也是proceed()方法

但是每次递归,索引都是自增一次,当自增到一定程度就会执行

return invokeJoinpoint();

如果五种通知并存,那么就会有这样的顺序

我们注意到MethodBeforeAdviceInterceptor中是这样的

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
   return mi.proceed();
}
说明这个会执行掉前置通知中的方法,然后再mi.proceed()

最终索引自增到一定程度然后执行

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }

这时候目标类的方法会被执行

然后返回到上一层的after通知器

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
      return mi.proceed();
   }
   finally {
      invokeAdviceMethod(getJoinPointMatch(), null, null);
   }
}

执行invokeAdviceMethod,也就是后置处理

然后再执行return的通知器

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   Object retVal = mi.proceed();
   this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
   return retVal;
}

然后在执行throwing的通知器

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
      return mi.proceed();
   }
   catch (Throwable ex) {
      if (shouldInvokeOnThrowing(ex)) {
         invokeAdviceMethod(getJoinPointMatch(), null, ex);
      }
      throw ex;
   }

这里如果没出现异常就不会到catch中,否则继续返回 mi.proceed();

最后再执行通用的ExposeInvocationInterceptor,

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   MethodInvocation oldInvocation = invocation.get();
   invocation.set(mi);
   try {
      return mi.proceed();
   }
   finally {
      invocation.set(oldInvocation);
   }
}

最终我们返回结果

ok,完工,这就是spring aop的完整原理!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值