Spring AOP源码深度解析

Spring AOP源码深度解析

本文将从源码层面深入剖析Spring AOP的实现原理,包括AOP核心组件、代理创建机制、通知执行流程以及与AspectJ的集成等关键内容。

一、Spring AOP核心组件

1. AOP核心接口体系

Spring AOP基于以下核心接口构建5:

java 复制代码
// 切面接口
public interface Aspect {
    // 定义切面相关信息
}

// 通知接口(Advice)
public interface Advice {
    // 通知是切面的具体实现逻辑
}

// 切入点接口(Pointcut)
public interface Pointcut {
    ClassFilter getClassFilter();
    MethodMatcher getMethodMatcher();
}

// 顾问接口(Advisor),组合了切入点和通知
public interface Advisor {
    Advice getAdvice();
    boolean isPerInstance();
}

// 增强器接口(IntroductionAdvisor)
public interface IntroductionAdvisor extends Advisor {
    ClassFilter getClassFilter();
    void validateInterfaces() throws IllegalArgumentException;
    Class<?>[] getInterfaces();
}

2. 通知类型体系

Spring AOP支持五种通知类型,每种类型都有对应的接口:

java 复制代码
// 前置通知
public interface MethodBeforeAdvice extends BeforeAdvice {
    void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}

// 后置通知
public interface AfterReturningAdvice extends AfterAdvice {
    void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
}

// 环绕通知
public interface MethodInterceptor extends Interceptor {
    Object invoke(MethodInvocation invocation) throws Throwable;
}

// 异常通知
public interface ThrowsAdvice extends AfterAdvice {
    // 无方法定义,需要自定义实现特定签名的方法
}

二、Spring AOP代理创建机制

1. AOP代理创建入口

Spring AOP代理创建的核心入口是AbstractAutoProxyCreator类,它实现了BeanPostProcessor接口,在Bean初始化后为符合条件的Bean创建代理对象5:

java 复制代码
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 检查是否已经处理过
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // 获取适用于当前Bean的通知器
        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;
    }
}

2. 代理类型选择机制

Spring AOP通过DefaultAopProxyFactory决定使用JDK动态代理还是CGLIB代理4:

java 复制代码
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // 决定使用JDK动态代理还是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);
        }
    }

    // 判断目标类是否没有实现用户提供的接口
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] interfaces = config.getProxiedInterfaces();
        return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.isAssignableFrom(interfaces[0])));
    }
}

3. JDK动态代理实现

JdkDynamicAopProxy实现了InvocationHandler接口,通过JDK的反射机制创建代理对象2:

java 复制代码
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

    private final AdvisedSupport advised;

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 创建JDK动态代理实例
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            // 处理Object类的方法
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            // 设置代理上下文(如果需要)
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // 获取目标对象
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 获取适合此方法的拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 如果没有拦截器,直接调用目标方法
            if (chain.isEmpty()) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // 创建方法调用
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // 执行拦截器链
                retVal = invocation.proceed();
            }

            // 处理返回值
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target && returnType != Object.class &&
                    returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}

4. CGLIB代理实现

CglibAopProxy使用CGLIB库创建代理对象,适用于目标类没有实现接口的情况3:

java 复制代码
public class CglibAopProxy implements AopProxy, Serializable {

    private final AdvisedSupport advised;

    @Override
    public Object getProxy(@Nullable 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;
            // 处理代理类
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // 验证并准备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));

            // 创建回调数组
            Callback[] callbacks = getCallbacks(rootClass);
            enhancer.setCallbacks(callbacks);
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));

            // 创建并返回代理实例
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class", ex);
        }
        catch (Throwable ex) {
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

    // 内部类MethodInterceptor实现了CGLIB的MethodInterceptor接口
    private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

        private final AdvisedSupport advised;

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {
                // 类似JDK动态代理的逻辑
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
                
                // 获取拦截器链
                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 {
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                
                return retVal;
            }
            finally {
                // 清理工作
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }
    }
}

三、通知执行机制

1. 拦截器链的创建

Spring AOP将通知转换为拦截器链,然后按顺序执行。核心逻辑在AdvisedSupport类中:

java 复制代码
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}

2. 拦截器链的执行

通知执行的核心逻辑在ReflectiveMethodInvocation类的proceed()方法中,它实现了责任链模式1:

java 复制代码
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

    protected final Object proxy;
    @Nullable
    protected final Object target;
    protected final Method method;
    protected Object[] arguments;
    @Nullable
    private final Class<?> targetClass;
    protected final List<Object> interceptorsAndDynamicMethodMatchers;
    private int currentInterceptorIndex = -1;

    @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;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            } else {
                // 不匹配,跳过此拦截器
                return proceed();
            }
        } else {
            // 静态拦截器,直接执行
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

    protected Object invokeJoinpoint() throws Throwable {
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }
}

3. 各种通知类型的实现

MethodBeforeAdviceInterceptor为例,展示前置通知的实现:

java 复制代码
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

    private final MethodBeforeAdvice advice;

    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 先执行前置通知
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        // 再执行后续拦截器或目标方法
        return mi.proceed();
    }
}

环绕通知的实现(以AspectJAfterThrowingAdvice为例):

java 复制代码
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            // 执行后续拦截器或目标方法
            return mi.proceed();
        } catch (Throwable ex) {
            // 如果有异常,检查是否是需要处理的异常类型
            if (shouldInvokeOnThrowing(ex)) {
                // 调用异常通知方法
                invokeAdviceMethod(getJoinPointMatch(), null, ex);
            }
            throw ex;
        }
    }

    private boolean shouldInvokeOnThrowing(Throwable ex) {
        return getAspectJAdviceMethod().getParameterTypes()[2].isAssignableFrom(ex.getClass());
    }
}

四、Spring AOP与AspectJ集成

1. @EnableAspectJAutoProxy注解分析

@EnableAspectJAutoProxy注解是Spring启用AspectJ风格AOP的核心5:

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * 是否代理目标类,true使用CGLIB,false使用JDK动态代理
     */
    boolean proxyTargetClass() default false;

    /**
     * 是否暴露代理对象到ThreadLocal
     */
    boolean exposeProxy() default false;

}

2. AspectJAutoProxyRegistrar实现

java 复制代码
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

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

        // 注册AOP相关基础设施
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        // 获取@EnableAspectJAutoProxy注解的属性
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            // 设置proxyTargetClass属性
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            // 设置exposeProxy属性
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}

3. AnnotationAwareAspectJAutoProxyCreator分析

AnnotationAwareAspectJAutoProxyCreator是Spring AOP与AspectJ集成的核心类,它负责扫描@Aspect注解的类并创建代理:

java 复制代码
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    @Nullable
    private AspectJAdvisorFactory aspectJAdvisorFactory;

    @Nullable
    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;

    @Override
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.initBeanFactory(beanFactory);
        if (this.aspectJAdvisorFactory == null) {
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }
        this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // 先调用父类方法获取Spring AOP的Advisor
        List<Advisor> advisors = super.findCandidateAdvisors();
        // 再添加AspectJ的Advisor
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }
}

4. AspectJ注解解析

BeanFactoryAspectJAdvisorsBuilder负责扫描和解析@Aspect注解的类:

java 复制代码
public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                // 获取所有Bean的名称
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                // 遍历所有Bean,查找@Aspect注解的类
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    // 获取Bean的类型
                    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);
                            // 解析Aspect类中的通知方法,创建Advisor
                            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;
            }
        }
    }

    // 从缓存中获取Advisor
    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String aspectName : aspectNames) {
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        } else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            if (factory != null) {
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
    }
    return advisors;
}

五、Spring AOP与AspectJ的区别

特性 Spring AOP AspectJ
实现方式 基于动态代理(JDK/CGLIB) 编译时织入(CTW)、后编译织入或加载时织入(LTW)
支持的连接点 仅限方法执行 全面(方法、构造器、字段、异常处理点等)
性能 运行时开销较大 编译时处理,运行时无额外开销
功能范围 仅支持方法级别的切面 支持字段、构造器、方法等更细粒度切面
织入时机 运行时织入 编译时/加载时织入
学习曲线 较简单 较复杂
依赖 仅需Spring框架 需要AspectJ编译器或织入器
适用场景 适合大多数Spring应用 需要更强大切面功能或更高性能要求的场景

六、Spring AOP工作流程总结

Spring AOP的完整工作流程可以概括为以下几个主要步骤:

  1. AOP配置解析:解析@AspectJ注解或XML配置,识别切面、通知和切入点
  2. 注册自动代理创建器:通过@EnableAspectJAutoProxy注册AnnotationAwareAspectJAutoProxyCreator
  3. 扫描切面类:扫描并解析带有@Aspect注解的类,将通知方法转换为Advisor
  4. 创建代理对象:在Bean初始化后,AbstractAutoProxyCreator为符合条件的Bean创建代理
  5. 选择代理类型:根据目标类是否实现接口,选择JDK动态代理或CGLIB代理
  6. 执行增强逻辑:当调用代理对象的方法时,按照责任链模式执行各种通知

总结

Spring AOP是Spring框架的核心特性之一,它通过动态代理机制在运行时为目标对象创建代理,并在代理中织入增强逻辑。深入理解Spring AOP的源码实现,不仅有助于我们更好地使用AOP功能,也能让我们学习到优秀的设计模式和编程思想。

Spring AOP的设计非常灵活,它通过责任链模式处理各种通知,通过工厂模式创建代理对象,并与IoC容器紧密集成,为Java应用提供了强大的面向切面编程支持。

相关推荐
HenryLin2 小时前
Kronos核心概念解析
后端
货拉拉技术2 小时前
大规模 Kafka 消费集群调度方案
后端
oak隔壁找我2 小时前
MyBatis Plus 源码深度解析
java·后端
oak隔壁找我2 小时前
Druid 数据库连接池源码详细解析
java·数据库·后端
剽悍一小兔2 小时前
Nginx 基本使用配置大全
后端
LCG元2 小时前
性能排查必看!当Linux服务器CPU/内存飙高,如何快速定位并"干掉"罪魁祸首进程?
linux·后端
oak隔壁找我2 小时前
MyBatis 源码深度解析
java·后端
lang201509282 小时前
Spring 4.1新特性:深度优化与生态整合
java·后端·spring
纳就这样吧2 小时前
Spring Cloud中@EnableDiscoveryClient注解详解
spring boot·后端·spring cloud