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

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()方法的递归调用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容