Spring AOP源码解读

本文深入探讨了Spring AOP的运行时增强,详细解析了Spring如何通过JDK动态代理和CGLIB生成AOP代理对象,重点介绍了ProxyFactoryBean的源码,阐述了其初始化通知器链、获取单例和原型AOP对象的过程。文章还对比了Spring AOP与AspectJ的区别,并分析了切点和切面的概念以及Spring的切面类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、概述

二、SpringAOP运行时增强

三、Spring AOP的常用类

四、Spring AOP源码分析

1.XML 配置

2.ProxyFactoryBean生成AOP代理对象

3.具体的两种代理对象生成源码

1、 JDK动态代理:

2、CGLIB动态代理

五、切点和切面分析

六、参考


一、概述

  1. AOP(Aspect Orient Programming):面向切面编程;
    用途:用于系统中的横切关注点,比如日志管理,事务管理;
    实现:利用代理模式,通过代理对象对被代理的对象增加功能。所以,关键在于AOP框架自动创建AOP代理对象,代理模式分为静态代理和动态代理;
    框架
    AspectJ使用静态代理,编译时增强,在编译期生成代理对象;
    SpringAOP使用动态代理,运行时增强,在运行时,动态生成代理对象;
  2. AspectJ框架;
    经过AspectJ的编译器编译后的java字节码,会比java源码多一些代码,即在编译阶段,将定义的Aspect切面织入Java字节码中,运行时就是已经被增强过的类了;支持到方法、字段,构造器级别
  3. SpringAOP框架;
    区别于AspectJ,Spring AOP使用的是动态代理,不修改字节码,而是运行时在内存中临时创建一个AOP代理对象,AOP对象包含了被代理对象的全部方法,并在特定的切点做了增强处理,回调被代理对象的方法;支持到方法级别

二、SpringAOP运行时增强

Spring AOP动态代理主要是两种方式,JDK动态代理和CGLIB动态代理。

  • JDK动态代理:通过反射来接收被代理的类,并且被代理的类必须实现接口;
    核心是:java.lang.reflect.InvocationHandler接口 与 java.lang.reflect.Proxy类;
  • CGLIB动态代理:目标类没有实现接口,Spring AOP会选择使用CGLIB在运行时动态的生成某个类的子类,因此,CGLIB是通过继承的方式,用子类实现对目标类的增强,final class不可继承的类,无法使用CGLIB做动态代理。
  • Spring的AOP与IOC:Spring AOP对象由Spring IOC容器自动生成、管理,其依赖关系也由IOC容器负责管理,那么AOP对象可以直接使用容器中的其他Bean实例作为被代理对象,所以此时使用SpringAOP只需要定义切点(pointcut)和 增强(advice)即可。
  • AOP代理的方法通过在目标对象的切入点动态的织入增强处理,完成对目标方法的增强。

三、Spring AOP的常用类

ProxyConfig类的继承结构
  • ProxyConfig类:所有Spring AOP生成的代理对象的基类,主要为其AOP代理对象工厂实现类提供配置属性。
public class ProxyConfig implements Serializable {

    private boolean proxyTargetClass = false;
    private boolean optimize = false;
    boolean opaque = false;
    boolean exposeProxy = false;
    private boolean frozen = false;

    public void copyFrom(ProxyConfig other) {
        Assert.notNull(other, "Other ProxyConfig object must not be null");
        this.proxyTargetClass = other.proxyTargetClass;
        this.optimize = other.optimize;
        this.exposeProxy = other.exposeProxy;
        this.frozen = other.frozen;
        this.opaque = other.opaque;
    }
}
  • AdvisedSupport类:ProxyConfig类的子类,封装了AOP中通用的对增强(Advice)和通知器(Advisor)的相关操作,对于所有生成AOP代理对象都通用,而代理对象的生成由子类完成;
  • ProxyCreatorSupport类:AdvisedSupport类的子类,一个AOP对象创建的辅助类,提供不同的AOP代理对象生成的通用方法,而代理对象的生成由其子类完成。
  • 实际创建AOP对象的类:AspectJProxyFactory、ProxyFactory、ProxyFactoryBean;工厂类;ProxyCreatorSupport的子类;
  1. AspectJProxyFactory:创建AspectJ的AOP对象,用于Spring集成AspectJ的作用,此时,就不需要使用AspectJ特定的编译器了。
  2. ProxyFactory:创建编程式的AOP对象;
  3. ProxyFactoryBean:创建声明式的AOP对象,通过配置创建AOP对象;

四、Spring AOP源码分析

以ProxyFactoryBean为例,分析Spring AOP的实现原理。

1.XML 配置

<!-- 切面 -->
<bean id="logAdvice" class="com.test.advice.LogAdvice"/>
<!--配置AOP代理工厂,封装AOP功能的主要类-->
<bean id="requestProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- AOP 代理接口 -->
    <property name="proxyInterfaces">
        <value>com.test.Request</value>
    </property>

    <!-- 需要增强的对象 -->
    <property name="target">
        <bean class="com.test.StringRequest" />
    </property>

    <!--代理拦截器,配置通知器的名称,即通知器在AOP代理的配置下通过使用代理对象的拦截机制发挥作用-->
    <property name="interceptorNames">
        <list>
            <value>logAdvice</value>
        </list>
    </property>

    <!-- 是否接口类:true说明ProxyFactoryBean要代理的不是接口类,而是CGLIB方式来进行代理 -->
    <property name="proxyTargetClass" value="false"/>

</bean>

2.ProxyFactoryBean生成AOP代理对象

ProxyFactoryBean配置目标对象和切面行为Advice,通过其配置的拦截器名称interceptorNames即通知器Advisor将切面应用到目标对象中。

ProxyFactoryBean的功能:

  1. 初始化通知器链
  2. 获取单例、原型的Aop代理对象

public class ProxyFactoryBean extends ProxyCreatorSupport
        implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {

    // 标记通知器的为全局通知器
    public static final String GLOBAL_SUFFIX = "*";

    // 通知器链是否已经初始化
    private boolean advisorChainInitialized = false;

    // 如果是单例,缓存单例对象
    private Object singletonInstance;

    // 实际上是:new DefaultAdvisorAdapterRegistry();Advisor适配器注册,将Advice适配成Advisor
    private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();


     // 创建AOPProxy代理对象的入口
    public Object getObject() throws BeansException {
        // 初始化通知器链
        initializeAdvisorChain();

        if (isSingleton()) { // 单例
            return getSingletonInstance();
        }
        else { // 原型
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }

    // 初始化通知器链(同步方法)
    private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        if (this.advisorChainInitialized) {
            // 如果通知器链已经初始化,直接返回
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) { // 如果配置的拦截器名称存在
            // 如果没有bean容器,抛出异常
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            // 全局通知器不能是通知器链中最后一个,除非显示的指定了目标
            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // 遍历通知器链名称
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }
                // 如果通知器是全局的
                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    // 向容器中添加全局通知器
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.subs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值