Spring AOP 代理过程分析

@EnableAspectJAutoProxy 注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    // 使用CGLIB代理
    boolean proxyTargetClass() default false;
    // 是否暴露代理对象
    boolean exposeProxy() default false;
}

在这个注解中引入AspectJAutoProxyRegistrar,它是ImportBeanDefinitionRegistrar接口的实现。
ImportBeanDefinitionRegistrar接口和ImportSelector接口是Spring中两个扩展接口,分别通过registerBeanDefinitions方法和selectImports方法向容器注入Bean。
AspectJAutoProxyRegistrar的registerBeanDefinitions方法:

public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    // 注册AnnotationAwareAspectJAutoProxyCreator 
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    // proxyTargetClass:true强制使用CGLIB代理  
    if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }
    // 是否暴露代理对象 
    if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
        AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
}

1、进入AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法会发现这个方法将一个类AnnotationAwareAspectJAutoProxyCreator注册到了容器中。
2、proxyTargetClass=true则强制使用CGLIB代理,否则会根据目标类是否实现了接口,自动选择是JDK代理或者是CGLIB代理。
3、有时候目标对象内部的自我调用无法实施切面中增强exposeProxy=true会将代理对象暴漏到AopContext中,此时使用AopContext.currentProxy即可。

AOP切入点

AnnotationAwareAspectJAutoProxyCreator类的继承关系为:

BeanPostProcessor
|
SmartInstantiationAwareB
|
AbstractAutoProxyCreator
|
AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessor接口的实现。
BeanPostProcessor这个接口Spring中一个特殊且重要的接口,会在容器实例化Bean的时候调用,调用不止一次,比如会在实例化前,实例化后,属性填充后等等适合的时机调用BeanPostProcessor的实现。具体参见spring容器加载分析 一容器构造。

大致梳理下Bean的实例化过程:

在AbstractAutowireCapableBeanFactory类中有具体的Bean实例化方法doCreateBean:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    1: 实例化Bean
    instanceWrapper = createBeanInstance(beanName, mbd, args); 
    2: 是否需要提早曝光:单例&允许循环依赖&当前bean增在创建中,检查循环依赖
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                        isSingletonCurrentlyInCreation(beanName));
    3: 对bean的各种属性进行填充,有可能依赖其他bean,递归初始化   step4.2.3
    4: 调用初始化方法init-method、此处也有机会返回Bean的代理对象
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    5: 解决循环依赖
    return exposedObject;
}

进入initializeBean方法:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    1:如果Bean有InitMethod开始调用
    invokeInitMethods(beanName, wrappedBean, mbd);
    2: 调用BeanPostProcessors的postProcessBeforeInitialization方法
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    3: 调用BeanPostProcessors的postProcessAfterInitialization方法
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    // 如果启用了AOP此处应该返回了代理对象,也就是说原来初始化的bean被替换了。
    return wrappedBean;
}

AOP生成代理的切入点就在applyBeanPostProcessorsAfterInitialization方法中了,遍历BeanPostProcessor列表然后依次调用postProcessAfterInitialization方法,AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法中正好返回了Bean的代理对象,则代理对象在doCreateBean方法中替换掉了原生的Bean实例。

代理对象生成和切面织入过程

postProcessAfterInitialization方法的实现:

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 不存在代理,生成
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 已处理过
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //判断给定的BEAN是否是一个基础设施类  ,基础设施类不应代理或者配置了指定的BEAN不需要代理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    // 如果目标类存在advice则创建代理.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

只有存在advice(增强)的Bean才会创建代理,getAdvicesAndAdvisorsForBean就是获取绑定到Bean上的advice列表,如果列表为空则不创建代理。

获取advice列表在类AnnotationAwareAspectJAutoProxyCreator中。

protected List findCandidateAdvisors() {
    // 调用父类的方法去查找Advisors,查找所有实现了org.springframework.aop.Advisor接口的BEAN
    // 主要是为了不遗漏XML配置的advisors
    List advisors = super.findCandidateAdvisors();
    // AspectJ注解的Advisor
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

第一步先获取实现了Advisor接口的Bean,使用BeanFactoryUtils.beanNamesForTypeIncludingAncestors方法。
第二步获取有@Aspect注解的Bean,委托给了BeanFactoryAspectJAdvisorsBuilder类,解析方法buildAspectJAdvisors()处理过程如下:

1:获取所有的beanNames,再由beanFactory.getType(beanName)获取Bean的class列表
2:判断是否包含@Aspect注解
3:解析成Advisor列表
4:使用AopUtils.findAdvisorsThatCanApply检查Advisor与Bean是否匹配,过滤掉不匹配的Advisor。

如果Advisor列表不为空则进入代理创建逻辑,

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);
    //判定给定的bean是否代理Class
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }else {
            // 评估解析代理的接口
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // 添加Advisors
    proxyFactory.addAdvisors(advisors);
    // 设置目标类
    proxyFactory.setTargetSource(targetSource);
    // 定制代理
    customizeProxyFactory(proxyFactory);
    // 设置是否冻结,默认为false即代理设置后不允许修改代理的配置
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    return proxyFactory.getProxy(getProxyClassLoader());
}

ProxyFactory中委托DefaultAopProxyFactory类来确定Bean的代理类型

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // 对生成代理策略进行优化||强制使用CGLIB来实现代理||不适用接口代理
    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 {
        // JDK代理
        return new JdkDynamicAopProxy(config);
    }
}

此时已经确定了Bean是使用JDK代理还是使用CGLIB代理,JDK代理使用
JdkDynamicAopProxy来生成代理类、CGLIB代理使用ObjenesisCglibAopProxy来生成代理类。
ObjenesisCglibAopProxy代理类的生成过程:

public Object getProxy(ClassLoader classLoader) {
    try {
        // 目标对象
        Class rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
        Class proxySuperClass = rootClass;
        // 目标对象是否是CGLIB的代理对象
        if (ClassUtils.isCglibProxyClass(rootClass)) {
            proxySuperClass = rootClass.getSuperclass();
            Class[] additionalInterfaces = rootClass.getInterfaces();
            for (Class additionalInterface : additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
            }
        }
        // 验证类,主要是验证final方法
        validateClassIfNecessary(proxySuperClass, classLoader);
        // CGLIB的增强器
        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                    ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
        // 获取类的回调列表,都是MethodInterceptor的实例
        // 最主要的DynamicAdvisedInterceptor,这个就是动态织入增强的拦截器
        Callback[] callbacks = getCallbacks(rootClass);
        Class[] types = new Class[callbacks.length];
        for (int x = 0; x < types.length; x++) {
            types[x] = callbacks[x].getClass();
        }
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
                this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);
        return createProxyClassAndInstance(enhancer, callbacks);
    }
}

这个方法就是创建代理的核心方法,主要是获取目标对象,获取类的回调列表,这个回调列表都是MethodInterceptor的实例,可以看成是方法的拦截器链。其中最主要的是DynamicAdvisedInterceptor,这个Interceptor为Bean的切点方法进行Advisor动态织入。

// proxy 代理对象 、method 目标类方法 、args 方法参数、 methodProxy 每个被代理的方法都对应一个MethodProxy对象
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    Class targetClass = null;
    Object target = null;
    try {
        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
        // 目标对象
        target = getTarget();
        if (target != null) {
            targetClass = target.getClass();
        }
        // 获取拦截器链
        List 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,递归调用拦截器链
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
        }
        // 返回实施增强之后的调用结果
        retVal = processReturnType(proxy, target, method, retVal);
        return retVal;
    }
}

intercept就是拦截代理类的方法,匹配切入点,如果方法可以切入则根据切入逻辑依次执行增强逻辑,如果不匹配切入点则直接执行目标类的方法,切入点匹配逻辑在DefaultAdvisorChainFactory类中实现。

码字不易,转载请保留原文连接[https://www.jianshu.com/p/f504afb066f9)

你可能感兴趣的:(Spring AOP 代理过程分析)