Spring注解驱动-AOP原理(五)

AOP:面向切面编程,是指在程序运行期间将某段代码切入到指定方法指定位置进行运行的编程方式,原理是动态代理。

创建主配置类MainConfigOfAOP.java,添加Spring AOP的依赖。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>

定义业务逻辑类。

package com.atguigu.aop;

public class Calculator {
    public int div(int a, int b) {
        System.out.println("Calculator.div");
        return a / b;
    }
}

我们希望在业务逻辑运行的时候(方法运行之前,方法运行之后,方法出现异常)打印日志。

定义一个日志切面类,这个切面类需要动态感知div()方法运行的进度,来执行不同的方法,这些方法在AOP中被称作通知,通知分为5种:前置通知、后置通知、返回通知、异常通知、环绕通知。创建一个LogAspects.java文件,把通知方法和目标方法绑定,也就是指定通知方法在目标方法的何时运行。将切面类和业务类加入到容器中,使用@Aspect告知Spring哪个类是切面类。

使用xml配置文件的时候,可以使用如下代码开启基于注解的切面功能。如果使用注解版,那就需要在主配置类上添加@EnableAspectJAutoProxy,开启基于注解的AOP模式。

<aop:aspectj-autoproxy/>
package com.atguigu.config;

import com.atguigu.aop.Calculator;
import com.atguigu.aop.LogAspects;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class MainConfigOfAOP {
    @Bean
    public Calculator calculator() {
        return new Calculator();
    }

    @Bean
    public LogAspects logAspects() {
        return new LogAspects();
    }
}
package com.atguigu.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

import java.util.Arrays;

@Aspect
public class LogAspects {
    // 抽取公共的切入点表达式
    @Pointcut("execution(public int com.atguigu.aop.Calculator.*(..))")
    public void pointCut() {
    }

    // 前置通知:目标方法执行之前
    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint) {
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println(name + "\tLogAspects.logStart\t" + Arrays.asList(args));
    }

    // 后置通知:目标方法运行之后(正常运行结束和异常运行结束)
    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint) {
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println(name + "\tLogAspects.logEnd\t" + Arrays.asList(args));
    }

    // 返回通知:目标方法正常返回
    @AfterReturning(value = "pointCut()", returning = "result")
    // JoinPoint参数一定要在参数列表的第一个,否则报错
    public void logReturn(JoinPoint joinPoint, Object result) {
        String name = joinPoint.getSignature().getName();
        System.out.println(name + "\tLogAspects.logReturn\t" + result);
    }

    // 异常通知:目标方法出现异常
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    // JoinPoint参数一定要在参数列表的第一个,否则报错
    public void logException(JoinPoint joinPoint, Exception exception) {
        String name = joinPoint.getSignature().getName();
        System.out.println(name + "\tLogAspects.logException\t" + exception);
    }

    // @Around:环绕通知
    // 需要显式调用目标方法,jproceedingJoinPoint.proceed();
    // 方法需要有返回值,否则真正调用者拿不到返回值,会报空指针异常
    @Around("pointCut()")
    public Object logAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("LogAspects.logAround前");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("LogAspects.logAround后");
        return proceed;
    }
}

编写测试方法测试,这里一定要使用Spring容器中的对象,自己new对象是看不到AOP效果的。

package com.atguigu;

import com.atguigu.aop.Calculator;
import com.atguigu.config.MainConfigOfAOP;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AOPTest {
    @Test
    public void testAOP() {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
        // 自己new对象调用方法,是无效的,需要使用Spring容器中的对象
        Calculator bean = annotationConfigApplicationContext.getBean(Calculator.class);
        bean.div(1, 1);
        annotationConfigApplicationContext.close();
    }
}
  1. 将业务类和切面类都加入到Spring容器中,使用@Aspect注解告诉Spring哪个是切面类
  2. 在切面类的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
  3. 开启基于注解的AOP模式,在主配置类上标注@EnableAspectJAutoProxy 

1.AOP原理-@EnableAspectJAutoProxy

点击@EnableAspectJAutoProxy注解,可以发现,在它上面有一个@Import注解,用于给容器中导入AspectJAutoProxyRegistrar.class组件。AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,通过registerBeanDefinitions()方法可以自定义给容器中注册bean,通过源码,我们可知通过registerBeanDefinitions()方法给容器中注入了一个AnnotationAwareAspectJAutoProxyCreator(注解模式装配的AspectJ切面自动代理创建器)组件。

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    // 使用AopConfigUtils来注册一个AspectJAnnotationAutoProxyCreator组件,如果需要的情况下
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    // 获取EnableAspectJAutoProxy注解的内容信息
    AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    // 根据注解上的信息,做一些处理
    if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }
    if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
        AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
}

// 点击registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法后
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}

// 点击registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法后
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

// 点击registerOrEscalateApcAsRequired()方法后
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // 如果容器中已经包含internalAutoProxyCreator组件
    if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
        BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    } else {// 如果容器中没有internalAutoProxyCreator组件,根据传进来的参数AnnotationAwareAspectJAutoProxyCreator创建一个beanDefinition
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", -2147483648);
        beanDefinition.setRole(2);
        // 根据beanDefinition的属性注册bean,bean的名字是org.springframework.aop.config.internalAutoProxyCreator
        registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
        return beanDefinition;
    }
}

2.AOP原理-AnnotationAwareAspectJAutoProxyCreator分析

查看AnnotationAwareAspectJAutoProxyCreator的继承关系。

其中AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor,这里的SmartInstantiationAwareBeanPostProcessor继承自InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor继承自BeanPostProcessor,看到这里,就找到了熟悉的BeanPostProcessor了,这不是前面提到的bean后置处理器嘛。

在AbstractAutoProxyCreator中可以看到setBeanFactory()方法和postProcessBeforeInstantiation()方法。

在AbstractAdvisorAutoProxyCreator中重写了setBeanFactory()方法,在setBeanFactory()中调用了initBeanFactory()方法。

在AnnotationAwareAspectJAutoProxyCreator中有initBeanFactory()方法。

分别在这些方法里打上断点,之后用debug模式运行。

3.AOP原理-注册AnnotationAwareAspectJAutoProxyCreator

通过调用栈进行分析。

// 测试方法中
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);// 创建IOC容器,将主配置类参数传进去

// AnnotationConfigApplicationContext()构造方法中
this.register(annotatedClasses);// 注册配置类
this.refresh();// 刷新容器

// refresh()方法中
this.registerBeanPostProcessors(beanFactory);// 注册bean的后置处理器,用于拦截bean的创建

// registerBeanPostProcessors()方法中
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// 根据类型获取容器中的所有BeanPostProcessor
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// 额外给容器中添加BeanPostProcessor
// 定义了2个集合,将所有BeanPostProcessor分类保存
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList();
List<BeanPostProcessor> internalPostProcessors = new ArrayList();
// 根据BeanPostProcessor实现的接口对BeanPostProcessor进行分类
for(int var10 = 0; var10 < var9; ++var10) {
    ppName = var8[var10];
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 实现了PriorityOrdered接口的BeanPostProcessor
        pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
        priorityOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// 实现了Ordered接口的BeanPostProcessor
        orderedPostProcessorNames.add(ppName);
    } else {// 其他的BeanPostProcessor
        nonOrderedPostProcessorNames.add(ppName);
    }
}
// 优先给容器中注册实现了PriorityOrdered接口的BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, (List)priorityOrderedPostProcessors);
// 其次给容器中注册实现了Ordered接口的BeanPostProcessor
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, (List)orderedPostProcessors);
// 最后给容器中注册其余的BeanPostProcessor
registerBeanPostProcessors(beanFactory, (List)nonOrderedPostProcessors);
sortPostProcessors(internalPostProcessors, beanFactory);

// 在registerBeanPostProcessors()方法中,有getBean()方法,通过调用doGetBean(),getSingleton()方法,创建BeanPostProcessor对象,并保存到容器中

// doCreateBean()方法
if (instanceWrapper == null) {
    // 创建bean的实例
    instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
try {
    // 给bean的属性赋值
    this.populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
        // 调用initializeBean()方法初始化bean
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    }
} catch (Throwable var18) {
    if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
        throw (BeanCreationException)var18;
    }
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                // invokeAwareMethods()方法,根据不同的类执行不同初始化操作
                AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
                return null;
            }
        }, this.getAccessControlContext());
    } else {
        // invokeAwareMethods()方法,根据不同的类执行不同初始化操作
        this.invokeAwareMethods(beanName, bean);
    }
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 拿到所有的BeanPostProcessor,调用postProcessBeforeInitialization()方法
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    }
    try {
        // 调用invokeInitMethods()方法,表示执行自定义初始化方法
        this.invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 拿到所有的BeanPostProcessor,调用postProcessAfterInitialization()方法
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

// 在registerBeanPostProcessors()方法中,就是将BeanPostProcessor注册到BeanFactory中
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    Iterator var2 = postProcessors.iterator();
    while(var2.hasNext()) {
        BeanPostProcessor postProcessor = (BeanPostProcessor)var2.next();
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

4.AOP原理-AnnotationAwareAspectJAutoProxyCreator执行时机

继续查看refresh()方法。

// 执行finishBeanFactoryInitialization()方法完成BeanFactory的初始化工作,创建剩下的单实例bean
// 在finishBeanFactoryInitialization()方法中,执行创建
beanFactory.preInstantiateSingletons();

// 在preInstantiateSingletons()方法中,获取容器中所有的bean,调用this.getBean(beanName)方法依次创建
// 依次点击getBean(),doGetBean()方法
// 在doGetBean()方法中,先从缓存中获取当前bean,如果从缓存中获取到,包装后进行返回,如果获取不到,执行后序创建流程,对于单实例bean,只要是创建过,就会被缓存起来,下次直接从缓存中取

// createBean()方法
try {
    // 尝试返回一个代理对象,如果能创建出这个代理对象,直接返回,如果不能就走后续的doCreateBean()方法
    beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
    if (beanInstance != null) {
        return beanInstance;
    }
} catch (Throwable var8) {
    throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
}
// 执行真正的创建bean的方法
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isDebugEnabled()) {
    this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;

// resolveBeforeInstantiation()方法在真正创建之前有一个拦截,尝试通过后置处理器创建代理类
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = this.determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 获取所有后置处理器,如果符合instanceof InstantiationAwareBeanPostProcessor,就执行postProcessBeforeInstantiation()方法
                bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = bean != null;
    }
    return bean;
}

5.AOP原理-创建AOP代理

在每一个bean创建之前,都会调用postProcessBeforeInstantiation()方法。查看AbstractAutoProxyCreator类的postProcessBeforeInstantiation()方法。

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object cacheKey = this.getCacheKey(beanClass, beanName);
    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        // 判断当前bean是否在需要增强的bean中
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 如果当前类是Advice、Pointcut、Advisor、AopInfrastructureBean、切面类或者判断增强器是AspectJPointcutAdvisor类型
        if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
            // 这里的FALSE用于标识当前bean是否已经增强过,因为还没有执行增强,所以这里是false
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }
    if (beanName != null) {
        TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }
    return null;
}

执行完postProcessBeforeInstantiation()方法,执行postProcessAfterInitialization()方法。

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

// 在wrapIfNecessary()方法,获取当前bean的所有增强器(通知方法)
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
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;
} else {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

// AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean()方法->findEligibleAdvisors()方法->findAdvisorsThatCanApply()方法
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    List var4;
    try {
        // 使用AopUtils工具找到当前bean可以使用的AOP方法
        var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    } finally {
        ProxyCreationContext.setCurrentProxiedBeanName((String)null);
    }
    return var4;
}

// createProxy()方法
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
    }
    // 通过ProxyFactory创建代理类
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
    if (!proxyFactory.isProxyTargetClass()) {
        if (this.shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        } else {
            this.evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    // 获取所有的增强器,也就是通知方法
    Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
    // 把增强器添加到代理工厂
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    this.customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if (this.advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    // 通过代理工厂,创建代理类
    return proxyFactory.getProxy(this.getProxyClassLoader());
}

// 在DefaultAopProxyFactory类的createAopProxy()方法,会有两种形式的代理对象,一种是JdkDynamicAopProxy,一种是ObjenesisCglibAopProxy
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));
        }
    }
}

如果一个对象需要被增强,那么,从容器中获取的组件,实际上是一个代理对象,当执行目标方法的时候,代理对象会执行通知方法的流程。

6.AOP原理-获取拦截器链-MethodInterceptor

为了查看代理对象执行目标方法的情况,我们在目标方法调用的地方打断点,debug模式启动。

// CglibAopProxy的intercept()方法用于拦截目标方法的执行
// 根据ProxyFactory对象获取将要执行的目标方法拦截器链
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 {// 如果有拦截器链,创建一个CglibMethodInvocation对象,并调用proceed()方法
    retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
}
retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);

// AdvisedSupport#的getInterceptorsAndDynamicInterceptionAdvice()方法
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);

// DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice()方法
// 创建一个interceptorList用来存放所有的拦截器,方法最后,会将interceptorList进行返回
List<Object> interceptorList = new ArrayList(config.getAdvisors().length);
// 之后,遍历所有的增强器,根据每个增强器所属的类型不同,获取每个增强器的拦截器,放入interceptorList中

7.AOP原理-链式调用通知方法

着重研究CglibMethodInvocation对象的proceed()方法。

public Object proceed() throws Throwable {
    // currentInterceptorIndex默认值是-1,也表示当前正在处理的拦截器的索引,interceptorsAndDynamicMethodMatchers.size()是拦截器的个数
    // 当没有拦截器链的时候,interceptorsAndDynamicMethodMatchers.size()-1和currentInterceptorIndex的值都等于-1,直接执行目标方法
    // 当执行到最后一个拦截器的时候,currentInterceptorIndex和interceptorsAndDynamicMethodMatchers.size()-1的值都等于最后一个拦截器的索引,直接执行目标方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // 利用反射执行目标方法
        return this.invokeJoinpoint();
    } else {
        // 索引自增,拿到拦截器通知,在下面执行具体方法
        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
            return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
        } else {
            // 这里的invoke()方法,会调用MethodInvocation对象的proceed()方法,再次进入本方法继续执行后面的拦截器,每个拦截器都是这么操作,形成了一条链
            return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
        }
    }
}

// 最后一个拦截器MethodBeforeAdviceInterceptor的invoke()方法和其他拦截器的invoke()方法有所不同
public Object invoke(MethodInvocation mi) throws Throwable {
    // 先调用前置通知,再调用proceed()方法
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    return mi.proceed();
}

因为每一个拦截器都会调用一次proceed()方法,那么有多少拦截器,递归的深度就是多少,当最后一个拦截器执行完成后, 根据proceed()方法的判断,执行目标方法并返回给倒数第二个拦截器,如果这个拦截器的proceed()方法调用后面还有代码,就继续执行。如果出现异常,AspectJAfterThrowingAdvice的invoke()会将异常抛出去,如果后面没有异常处理,就抛给JVM了。依次执行下去,会执行到第一个拦截器。每一个拦截器需要等待下一个拦截器执行完成后返回再来执行方法,这就保证了通知方法和目标方法的执行顺序。

8.AOP-原理总结

  1. 通过注解@EnableAspectJAutoProxy开启AOP功能
  2. @EnableAspectJAutoProxy注解会向容器中注册一个AnnotationAwareAspectJAutoProxyCreator组件
  3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器
  4. 在refresh()方法中,通过调用registerBeanPostProcessor()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
  5. 在finishBeanFactoryInitialization()方法初始化剩余的单实例bean(切面bean,业务bean等),AnnotationAwareAspectJAutoProxyCreator会拦截组件的创建过程,组件创建完成后,判断组件是否需要增强,如果需要增强,给业务逻辑组件创建一个代理对象处理增强,默认使用cglib代理
  6. 代理对象执行目标方法,通过CglibAopProxy.intercept()方法进行拦截,得到目标方法的拦截器链,依次进入每个拦截器执行
  7. 正常执行:前置通知→目标方法→后置通知→返回通知;异常执行:前置通知→目标方法→后置通知→异常通知
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值