Spring AOP源码浅析

1. Spring AOP示例代码


示例代码结构如下图所示:

其中切面类AspectObject的代码:

@Aspect
@Component
public class AspectObject {

    //抽取公共的切入点表达式
    //1、本类引用
    //2、其他的切面引用
    @Pointcut("execution(public * io.zgc.spring.features.aop.annotation.TargetObject.*(..))")
    public void pointCut(){};

    //@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+ Arrays.asList(args)+"}");
    }

    @After("io.zgc.spring.features.aop.annotation.AspectObject.pointCut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
    }

    //JoinPoint一定要出现在参数表的第一位
    @AfterReturning(value="pointCut()",returning="result")
    public void logReturn(JoinPoint joinPoint,Object result){
        System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
    }
}

被代理类TargetObject的代码:

@Component
public class TargetObject implements TargetInterface{

    public String sayHello(String name) {
        System.out.println("hello,"+name);
        return "hello---"+name;
    }

}

测试客户端Client的代码:

package io.zgc.spring.features.aop.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Client {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);

        TargetInterface bean = applicationContext.getBean(TargetInterface.class);
        bean.sayHello("zgc");
        System.out.println(bean.getClass().getName());
    }
}

运行测试代码,输入如下结果

sayHello运行。。。@Before:参数列表是:{[zgc]}
hello,zgc
sayHello结束。。。@After
sayHello正常返回。。。@AfterReturning:运行结果:{hello---zgc}
com.sun.proxy.$Proxy21

从输出结果,可以看出TargetObject类,已经被Spring修改成了代理类com.sun.proxy.$Proxy21并在sayHello方法执行的织入了代理逻辑。接下来,我们就来分析下Spring是在什么地方以及通过什么方式将TargetObject替换成代理对象。

2. Debug调试


我们使用倒推的方式进行debug,重点关注我们需要关注的代码。

2.1. getBean调试

我们先假设代理对象实在获取bean的时候发生的。

TargetInterface bean = applicationContext.getBean(TargetInterface.class);

Debug跟进去发现,它最终是在singletonObjects中将代理对象获取出来的,而singletonObjects是个Map结构,它里面存放的是单例bean,可以简单将其理解为bean工厂(tips:这种理解并不准确)。

这里我们可以得出结论:代理对象的创建一定是包含在ApplicationContext对象创建的过程中

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);

那我们就在singletonObjects放置值的地方加上断点,再通过程序的调用栈尝试查看代理对象在什么地方生成。

为了减低干扰,断点需要加上条件beanName.equals("targetObject");

2.2. ApplicationContext创建debug

上面断点设置后,我们重新运行程序,可以看到以下程序调用栈

我们向上追溯一下调用栈上的代码,调用addSingleton()方法时已经将代理对象通过入参传递进来。而DefaultSingletonBeanRegistry#getSingleton()的伪代码如下:

  public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                ... ...
                try {
                    // 这里获取targetObject的代理对象,实际会调用createBean方法
                    singletonObject = singletonFactory.getObject();
                }
                ... ...
                addSingleton(beanName, singletonObject);
            }
            return singletonObject;
        }
    }

继续向上追溯, AbstractBeanFactory#doGetBean, 其伪代码如下:

protected  T doGetBean(final String name, @Nullable final Class requiredType,
                          @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    // Create bean instance.
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                ... ...
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    return (T) bean;
}

结合getSingletondoGetBean方法可知,当调用ObjectFactorygetObject方法时,会触发ObjectFactory类的createBean方法执行。

至此,我们知道了代理对象的创建是发生在createBean方法中,因此我们在此处增加条件断点,看看springcreateBean方法中做了哪些操作。

2.3. createBean调试

设置好断点之后,我们重新执行程序,一路step into

图中最下面的lambda$doGetBean就是我们给createBean设置断点的地方。最终程序执行到了AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization。其代码如下:

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

可以看到这里是遍历所有的BeanPostProcessor,然后依次执行其postProcessAfterInitialization方法。此时Spring运行的相关变量如下

这里注意一下,程序运行到这里,TargetObject对应的是原始对象,还没有被代理。

另外当前Spring上下文中包含的BeanPostProcessor中,有一个AnnotationAwareAspectJAutoProxyCreator。这个类是个后置处理器,它和代理对象的创建密不可分。

2.4. AnnotationAwareAspectJAutoProxyCreator调试

我们先来看看AnnotationAwareAspectJAutoProxyCreator类的继承结构

可以看到AnnotationAwareAspectJAutoProxyCreator类继承了BeanPostProcessorBeanFactoryAware。而BeanFactoryAware接口的postProcessAfterInitialization方法是在父类AbstractAutoProxyCreator中实现。

下面接着上面的applyBeanPostProcessors方法继续调试。

最终请求链路进入到ProxyCreatorSupport#createAopProxy方法(接下来的代码都是创建aop代理对象的核心逻辑),其源码如下:

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

DefaultAopProxyFactory#createAopProxy

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

最终调用JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)方法,其内部同步JDK动态代理,创建代理对象。

Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

至此,我们已经清楚的知道Spring是如何创建AOP代理对象。

2.5. 小结

Spring在创建IOC容器时,通过Spring提供的后置处理器扩展点,先向容器注册一个AnnotationAwareAspectJAutoProxyCreator后置处理器。再通过该后置处理器(其他后置处理器也如此)可以介入bean创建的生命周期,将原生bean通过JDK动态代理和cglib的方式替换成AOP代理类。

3. @EnableAspectJAutoProxy


上面还有一个疑问,AnnotationAwareAspectJAutoProxyCreator是怎么注册到IOC容器中的?答案就是@EnableAspectJAutoProxy

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

    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;

}

可以看到在@EnableAspectJAutoProxy注解中,为引入了(向容器注册)AspectJAutoProxyRegistrar类。

@Import(AspectJAutoProxyRegistrar.class)

AspectJAutoProxyRegistrar类最终会引入AnnotationAwareAspectJAutoProxyCreator后置处理器,相关代码如下:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

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

}

AopConfigUtils
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {

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

注册AnnotationAwareAspectJAutoProxyCreator的代码最终是需要创建IOC容器时来触发,调用链路图如下:

3.1. 创建和注册AnnotationAwareAspectJAutoProxyCreator流程

流程:
1)、传入配置类(或者配置文件),创建ioc容器
2)、注册配置类,调用refresh()刷新容器;
3)、registerBeanPostProcessors(beanFactory);注册bean的后置处理器来方便拦截bean的创建;


AnnotationAwareAspectJAutoProxyCreator创建时序图

1、先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
2、给容器中加别的BeanPostProcessor
3、优先注册实现了PriorityOrdered接口的BeanPostProcessor;
4、再给容器中注册实现了Ordered接口的BeanPostProcessor;
5、注册没实现优先级接口的BeanPostProcessor;
6、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;创建internalAutoProxyCreator BeanPostProcessor 【 AnnotationAwareAspectJAutoProxyCreator 】

  • 6.1. 创建Bean的实例
  • 6.2. populateBean;给bean的各种属性赋值
  • 6.3. initializeBean:初始化bean;
    • 6.3.1. invokeAwareMethods():处理Aware接口的方法回调
    • 6.3.2. applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
    • 6.3.3. invokeInitMethods();执行自定义的初始化方法
    • 6.3.4. applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
  • 6.4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;--》aspectJAdvisorsBuilder
    1. 把BeanPostProcessor注册到BeanFactory中;
beanFactory.addBeanPostProcessor(postProcessor);

你可能感兴趣的:(Spring AOP源码浅析)