美文网首页
Spring 源码(六)Spring AOP源码解析

Spring 源码(六)Spring AOP源码解析

作者: xiaolyuh | 来源:发表于2019-09-29 12:50 被阅读0次

    AOP 面向切面编程,相对于OOP面向对象编程。

    Spring AOP存在的目的是为了解耦。AOP可以让一组类共享相同的行为。在OOP中只能通过继承类和实现接口,来使代码的耦合度增强,且类继承只能是单继承,阻碍更多的行为添加到一组类上,AOP弥补了OOP的不足。

    Spring支持AspectJ的注解式切面编程,基本定义如下:

    1. 使用@AspectJ声明一个切面。
    2. 使用@After、@Before、@Around定义建言(adivice),可以直接将拦截规则(切点)作为参数。
    3. 其中@After、@Before、@Around参数的拦截规则为切点(PointCut),为了使切点复用,可以使用@PointCut专门定义拦截规则,然后在@After、@Before、@Around的参数中调用。
    4. 其中符合条件的每一个被拦截处为连接点(JoinPoint)。

    AspectJ提供了五种定义通知的标注:

    • @Before:前置通知,在调用目标方法之前执行通知定义的任务
    • @After:后置通知,在目标方法执行结束后,无论执行结果如何都执行通知定义的任务
    • @AfterReturning:后置通知,在目标方法执行结束后,如果执行成功,则执行通知定义的任务
    • @AfterThrowing:异常通知,如果目标方法执行过程中抛出异常,则执行通知定义的任务
    • @Around:环绕通知,在目标方法执行前和执行后,都需要执行通知定义的任务

    示例

    定义一个切入点

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Log {
        String value() default "";
    }
    

    声明一个切面

    // 切面
    @Aspect
    public class LogAspect {
    
        // 切点
        @Pointcut("@annotation(com.xiaolyuh.aop.annotations.Log)")
        public void pointCutMethod() {
        }
    
        @Pointcut("@within(com.xiaolyuh.aop.annotations.Log)")
        public void pointCutType() {
        }
    
        // 建言
        @Before("pointCutMethod() || pointCutType()")
    //    @Before("execution(* com.xiaolyuh.aop.controller.UserController.*(..))")
        public void before(JoinPoint joinPoint) {
            // 通过反射可以获得注解上的属性,然后做日志记录相关的操作
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Log log = method.getAnnotation(Log.class);
            System.out.println("日志切面 befor:" + log.value() + ":::" + JSON.toJSONString(joinPoint.getArgs()));
        }
    
        @After(value = " pointCutMethod() || pointCutType()")
        public void after(JoinPoint joinPoint) {
            // 通过反射可以获得注解上的属性,然后做日志记录相关的操作  
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Log log = method.getAnnotation(Log.class);
            System.out.println("日志切面 after:" + log.value());
        }
    
        @AfterReturning(value = " pointCutMethod() || pointCutType()", returning = "result")
        public void afterReturning(JoinPoint joinPoint, Object result) {
            // 通过反射可以获得注解上的属性,然后做日志记录相关的操作
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Log log = method.getAnnotation(Log.class);
            System.out.println("日志切面 afterReturning:" + log.value() + ":::" + JSON.toJSONString(result));
        }
    
        @AfterThrowing(value = " pointCutMethod() || pointCutType()", throwing = "t")
        public void afterThrowing(JoinPoint joinPoint, Throwable t) {
            // 通过反射可以获得注解上的属性,然后做日志记录相关的操作
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Log log = method.getAnnotation(Log.class);
            System.out.println("日志切面 afterThrowing:" + log.value() + ":::" + JSON.toJSONString(t.getStackTrace()));
        }
    
        @Around(value = " pointCutMethod() || pointCutType()")
        public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
            // 通过反射可以获得注解上的属性,然后做日志记录相关的操作
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Log log = method.getAnnotation(Log.class);
    
            System.out.println("日志切面 Around before:" + log.value() + ":::" + JSON.toJSONString(joinPoint.getArgs()));
            Object result = joinPoint.proceed();
            System.out.println("日志切面 Around after:" + log.value() + ":::" + JSON.toJSONString(result));
    
            return result;
        }
    }
    

    开启AOP的支持

    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan({"com.xiaolyuh.aop"})
    public class AopConfig {
    
        @Bean
        public LogAspect logAspect() {
            return new LogAspect();
        }
    }
    

    业务类的是用方式

    @Controller
    public class UserController {
    
        // 连接点
        @Log("除法接口")
        public Object div(int i, int j) {
            System.out.println("业务接口执行-------------------");
            return i / j;
        }
    
        public Object add(int i, int j) {
            return i + j;
        }
    }
    

    测试类

    public class AopTest extends BaseTest {
    
        @Before
        public void before() {
            super.before(AopConfig.class);
        }
    
        @Test
        public void contextTest() {
    
            PrintSpringBeanUtil.printlnBean(context);
            System.out.println("开始比较容器中的Bean");
            UserController bean = context.getBean(UserController.class);
            bean.div(4, 2);
        }
    }
    

    执行结果:

    日志切面 Around before:除法接口:::[4,2]
    日志切面 befor:除法接口:::[4,2]
    业务接口执行-------------------
    日志切面 Around after:除法接口:::2
    日志切面 after:除法接口
    日志切面 afterReturning:除法接口:::2
    

    注册 AnnotationAwareAspectJAutoProxyCreator 后置处理器

    @EnableAspectJAutoProxy

    @EnableAspectJAutoProxy的主要作用是开启对AOP的支持。源码如下:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
        // true:使用CGLIB, false:如果是接口使用JDK,不是接口使用CGLIB 
        boolean proxyTargetClass() default false;
        boolean exposeProxy() default false;
    }
    

    主要起作用的是@Import(AspectJAutoProxyRegistrar.class)AspectJAutoProxyRegistrar注册器的主要作用是将AnnotationAwareAspectJAutoProxyCreator后置处理器注册到容器中。

    AspectJAutoProxyRegistrar

    AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,实现该接口后Spring 在解析配置类的时候会通过后置处理器ConfigurationClassPostProcessor调用到 ImportBeanDefinitionRegistrar#registerBeanDefinitions() 方法,并将AnnotationAwareAspectJAutoProxyCreator后置处理器的Bean定义注册到容器中。

    对于 AOP 的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成的,它可以根据 @Point 注解定义的切点来自动代理相匹配的 bean。但是为了配置简便, Spring 使用了自定义配来帮助我们自动注册 AnnotationAwareAspectJAutoProxyCreator。实现如下:

    调用链路:

    registerOrEscalateApcAsRequired:121, AopConfigUtils (org.springframework.aop.config)
    registerAspectJAnnotationAutoProxyCreatorIfNecessary:90, AopConfigUtils (org.springframework.aop.config)
    registerAspectJAnnotationAutoProxyCreatorIfNecessary:86, AopConfigUtils (org.springframework.aop.config)
    registerBeanDefinitions:45, AspectJAutoProxyRegistrar (org.springframework.context.annotation)
    loadBeanDefinitionsFromRegistrars:360, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
    loadBeanDefinitionsForConfigurationClass:144, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
    loadBeanDefinitions:116, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
    processConfigBeanDefinitions:320, ConfigurationClassPostProcessor (org.springframework.context.annotation)
    postProcessBeanDefinitionRegistry:228, ConfigurationClassPostProcessor (org.springframework.context.annotation)
    invokeBeanDefinitionRegistryPostProcessors:272, PostProcessorRegistrationDelegate (org.springframework.context.support)
    invokeBeanFactoryPostProcessors:92, PostProcessorRegistrationDelegate (org.springframework.context.support)
    invokeBeanFactoryPostProcessors:687, AbstractApplicationContext (org.springframework.context.support)
    refresh:525, AbstractApplicationContext (org.springframework.context.support)
    <init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
    

    源码:

    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
        // 根据需要注册或升级 AbstractAdvisorAutoProxyCreator
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }
    
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            // 如果已经存在了自动代理创建器且存在的自动代理创建器与现在的不一致,那么需要根据优先级来判断到底需要使用那个AbstractAdvisorAutoProxyCreator
            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) {
                    // 改变bean最总要的是改变bean对应的className属性
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            // 如果已经存在的代理创建器与现在的一样,则不需要再次创建
            return null;
        }
        // 注册 AbstractAdvisorAutoProxyCreator
        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

    下面是AnnotationAwareAspectJAutoProxyCreator的类图,从类图我们可以看出AnnotationAwareAspectJAutoProxyCreator它是一个实现了Ordered接口的的后置处理器。和其他后置处理器一样,也会在registerBeanPostProcessors方法中完成后置处理器的实例化,并注册到Spring 容器。

    AnnotationAwareAspectJAutoProxyCreator.png

    解析切面类获取增强器

    找到增强器

    调用链路:

    buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
    findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
    shouldSkip:103, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
    postProcessBeforeInstantiation:248, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    applyBeanPostProcessorsBeforeInstantiation:1045, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    resolveBeforeInstantiation:1019, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:473, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
    getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
    preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
    refresh:543, AbstractApplicationContext (org.springframework.context.support)
    <init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
    

    源码:

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // 保持对XML配置的支持
        List<Advisor> advisors = super.findCandidateAdvisors();
        // 对注解方式的支持
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }
    
    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<Advisor>();
                    aspectNames = new LinkedList<String>();
                    // 获取所有的beanName
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    // 遍历beanName找到对应的class对象
                    for (String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
                        // 根据beanName获取class对象
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        // 判断是否是切面类(判断是否有@Aspect注解)
                        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);
                                // 解析标 AspectJ 注解中的增强方法
                                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);
                            }
                            ...
                        }
                    }
                    this.aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
        }
    
        ...
        return advisors;
    }
    

    切面类的解析其实就是去配置类中找加了Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class注解的方法。
    调用链路:

    findAspectJAnnotationOnMethod:129, AbstractAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    getPointcut:215, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    getAdvisor:203, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    getAdvisors:136, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
    

    源码:

    protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
        // 切点和建言的注解类
        Class<?>[] classesToLookFor = new Class<?>[] {
                Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
        for (Class<?> c : classesToLookFor) {
            // 找对应注解
            AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }
        return null;
    }
    

    通过调用链路我们可以看出,第一次解析切面类是在注册第一个单实例Bean到容器的时候,会执行后置处理器AnnotationAwareAspectJAutoProxyCreator 的 postProcessBeforeInstantiation 方法中。后续的单实例Bean注册到容器的时候会直接去缓存中的建言信息,不会再次解析切面类了。

    根据切点信息生成增强器

    我们找到增强器以后会统一封装成InstantiationModelAwarePointcutAdvisorImpl类型,它是Advisor的子类。因为不同的增强所体现的逻辑是不同的,比如@Before ("test()") 与 @After("tes()") 标签的不同就是增强器增强的位置不同 ,所以就需要不同的增强器来完成不同的逻辑。
    调用链路:

    getAdvice:255, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    instantiateAdvice:160, InstantiationModelAwarePointcutAdvisorImpl (org.springframework.aop.aspectj.annotation)
    <init>:106, InstantiationModelAwarePointcutAdvisorImpl (org.springframework.aop.aspectj.annotation)
    getAdvisor:209, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    getAdvisors:136, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
    buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
    findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
    shouldSkip:103, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
    postProcessBeforeInstantiation:248, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    applyBeanPostProcessorsBeforeInstantiation:1045, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    resolveBeforeInstantiation:1019, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:473, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
    getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
    preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
    refresh:543, AbstractApplicationContext (org.springframework.context.support)
    <init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
    

    源码:

    @Override
    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        ...
        AbstractAspectJAdvice springAdvice;
        // 根据不同的注解类型封装不同的增强器
        switch (aspectJAnnotation.getAnnotationType()) {
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }
    
        // Now to configure the advice...
        springAdvice.setAspectName(aspectName);
        springAdvice.setDeclarationOrder(declarationOrder);
        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        if (argNames != null) {
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        springAdvice.calculateArgumentBindings();
        return springAdvice;
    }
    

    从函数中可以看到,Spring 会根据不同的注解生成不同的增强器,例如 @Before 会对应
    AspectJMethodBeforeAdvice ,而在 AspectJMethodBeforeAdvice中完成了增强方法的逻辑。

    Advice关系图.png

    MethodBeforeAdviceInterceptor

    每个Advice又对应了一个MethodInterceptor,比如MethodBeforeAdvice就对应了MethodBeforeAdviceInterceptor。而我们对增强器的调用就是从MethodInterceptor的invoke方法开始的。 我们尝试分析一下MethodBeforeAdvice的增强器实现:

    public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
        // MethodBeforeAdvice 代表着置增强器 AspectJMethodBeforeAdvice
        private MethodBeforeAdvice advice;
    
        /**
         * Create a new MethodBeforeAdviceInterceptor for the given advice.
         * @param advice the MethodBeforeAdvice to wrap
         */
        public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
            Assert.notNull(advice, "Advice must not be null");
            this.advice = advice;
        }
    
        @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
            // 调用前置增强器的before方法
            this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
            return mi.proceed();
        }
    }
    
    // AspectJMethodBeforeAdvice
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
    
    protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
    }
    
    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
            actualArgs = null;
        }
        try {
            // 通过反射调用增强器
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            // TODO AopUtils.invokeJoinpointUsingReflection
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    this.aspectJAdviceMethod + "]; pointcut expression [" +
                    this.pointcut.getPointcutExpression() + "]", ex);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
    

    整个获取增强器的大致流程:

    1. 遍历所有注册到容器中的beanName,并根据beanName获取对应的Class
    2. 根据Class找出所有声明了@Aspect注解的类
    3. 对标记了@Aspect的类进行增强器的提取,其实就是去找加了@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut注解的方法。
    4. 将增强器封装成InstantiationModelAwarePointcutAdvisorImpl类型
    5. 将提取结果添加到缓存中

    创建增强Bean

    初始化ProxyFactory

    对于代理的创建和处理,Spring是委托给ProxyFactory去执行的,下面是对ProxyFactory进行初始化。调用链路:

    createProxy:466, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    wrapIfNecessary:349, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    postProcessAfterInitialization:298, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    applyBeanPostProcessorsAfterInitialization:423, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    initializeBean:1638, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    doCreateBean:555, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
    getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
    preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
    refresh:543, AbstractApplicationContext (org.springframework.context.support)
    <init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
    

    源码:

    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 = 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);
    
        // 用来控制代理工厂被配置后,是否允许修改通知,默认是false
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
    
        return proxyFactory.getProxy(getProxyClassLoader());
    }
    

    执行过程:

    1. 获取当前类中的属性
    2. 添加代理接口
    3. 封装Advisor并加入ProxyFactory中
    4. 设置代理类
    5. 执行自定义的函数customizeProxyFactory,在这里可以对ProxyFactory进行进一步封装
    6. 使用ProxyFactory获取代理

    创建 AopProxy 代理类

    ProxyFactory创建代理首先需要确定使用JDK代理还是Cglib代理。

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

    通过createAopProxy()方法确认需要使用那种代理,然后再去调用对应代理的getProxy()方法生成代理对象。

    调用链路:

    createAopProxy:51, DefaultAopProxyFactory (org.springframework.aop.framework)
    createAopProxy:105, ProxyCreatorSupport (org.springframework.aop.framework)
    getProxy:109, ProxyFactory (org.springframework.aop.framework)
    createProxy:466, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    wrapIfNecessary:349, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    postProcessAfterInitialization:298, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    applyBeanPostProcessorsAfterInitialization:423, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    initializeBean:1638, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    doCreateBean:555, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
    getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
    preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
    refresh:543, AbstractApplicationContext (org.springframework.context.support)
    <init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
    

    从调用链路上来看我们可以看到创建增强的Bean是在 后置处理器AnnotationAwareAspectJAutoProxyCreator 的 postProcessAfterInitialization 方法中,也就是完成初始化Bean之后执行。

    源码:

    @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.");
            }
            // 判断是否使用接口,如果是则使用JDK代理
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            // 使用CGliB代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }
    

    生成代理类

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

    JdkDynamicAopProxy和ObjenesisCglibAopProxy创建代理的实现可以参考Cglib 与 JDK动态代理

    执行增强Bean

    JdkDynamicAopProxy和CglibAopProxy采用了两种不同的方式:

    • Proxy.newProxyInstance()->JdkDynamicAopProxy(继承InvocationHandler接口).invoke(),然后匹配通知类型调用通知(通知就是@Before、@After等等),最后调用目标方法
    • Enhancer.Callback,Callback类似于InvocationHandler,类DynamicAdvisedInterceptor继承了Callback,它的intercept()方法就类似于invoke(),然后匹配通知类型调用通知,最后调用目标方法。

    不管是JdkDynamicAopProxy还是CglibAopProxy,最后都会将拦截链封装到ReflectiveMethodInvocation类中,然后调用proceed()方法执行拦截连。最后通过MethodInterceptor.invoke()方法执行每个增强逻辑。大致流程如下:


    Spring AOP 动态代理执行流程图.png

    调用量链路:

    before:33, LogAspect (com.xiaolyuh.aop.aspect)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:62, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:498, Method (java.lang.reflect)
    invokeAdviceMethodWithGivenArgs:627, AbstractAspectJAdvice (org.springframework.aop.aspectj)
    invokeAdviceMethod:609, AbstractAspectJAdvice (org.springframework.aop.aspectj)
    before:43, AspectJMethodBeforeAdvice (org.springframework.aop.aspectj)
    invoke:51, MethodBeforeAdviceInterceptor (org.springframework.aop.framework.adapter)
    proceed:168, ReflectiveMethodInvocation (org.springframework.aop.framework)
    invoke:47, AspectJAfterAdvice (org.springframework.aop.aspectj)
    proceed:168, ReflectiveMethodInvocation (org.springframework.aop.framework)
    invoke:52, AfterReturningAdviceInterceptor (org.springframework.aop.framework.adapter)
    proceed:168, ReflectiveMethodInvocation (org.springframework.aop.framework)
    invoke:62, AspectJAfterThrowingAdvice (org.springframework.aop.aspectj)
    proceed:168, ReflectiveMethodInvocation (org.springframework.aop.framework)
    invoke:92, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
    proceed:179, ReflectiveMethodInvocation (org.springframework.aop.framework)
    intercept:671, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
    div:-1, UserController$$EnhancerBySpringCGLIB$$a4147a00 (com.xiaolyuh.aop.controller)
    contextTest:22, AopTest (com.xiaolyuh.aop)
    

    源码:

    @Override
    public Object proceed() throws Throwable {
        //  执行完所有增强后执行切点方法(业务方法)
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
    
        // 获取下一个要执行的拦截器 
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // 动态匹配
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            // 判断是否需要执行拦截器
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // 动态匹配失败,该不执行拦截器,进入下一次循环
                return proceed();
            }
        }
        else {
            // 普通拦截器直接执行,比如:MethodBeforeAdviceInterceptor、AspectJAfterAdvice、AspectJAroundAdvice等
            // this作为参数传递,保证当前实例中调用链路的执行
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }
    

    ReflectiveMethodInvocation的主要职责是维护了链接调用的计数器,记录着当前调用链接的位置,以便链可以有序地进行下去,ReflectiveMethodInvocation只负责拦截链的调用,所有的增强逻辑都在各各增强器中进行实现。

    拦截链在封装到ReflectiveMethodInvocation中之前,拦截链的顺序就已经按照一定规则拍顺序了,拦截链的执行其实就是proceed()方法的递归调用。

    相关文章

      网友评论

          本文标题:Spring 源码(六)Spring AOP源码解析

          本文链接:https://www.haomeiwen.com/subject/mdisyctx.html