Spring AOP原理剖析:Spring和JDK源码对照+代理设计模式全解

导航:

【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析

目录

一、基本介绍

1.1 核心概念

1.1.1 AOP

1.1.2 连接点、切面、切入点、通知、顾问

1.2 代理设计模式 

二、源码解析

2.1 环境准备

2.2 initializeBean():初始化Bean和AOP 

2.2.1 doCreateBean()方法:创建Bean的核心逻辑处理方法

2.2.2 initializeBean():初始化Bean和AOP 

2.2.3 回顾BeanPostProcessor:Bean前后置处理器

2.3 applyBeanPostProcessorsBeforeInitialization():应用所有前置切面

2.4 applyBeanPostProcessorsAfterInitialization():应用所有后置切面

2.5 AbstractAutoProxyCreator类:代理创建器

2.6 postProcessAfterInitialization():初始化Bean后增强对象 

2.7 wrapIfNecessary():符合条件时包装代理对象  

2.8 createProxy():根据通知和顾问创建代理对象

2.9 getProxy():生成代理对象

2.9.1 createAopProxy():获取JDK或CGLIB代理实现类

2.9.2 JDK动态代理实现类

2.9.2.1 基本介绍

2.9.2.2 JdkDynamicAopProxy类:JDK动态代理实现类

2.9.2.3 getProxy():JDK代理生成代理对象

2.9.2.4 Proxy.newProxyInstance():JDK源码实例化代理类

2.9.3 CGLIB动态代理实现类

2.9.3.1 基本介绍

2.9.3.2 ObjenesisCglibAopProxy类: 集成Objenesis的CGLIB代理实现类

2.9.3.3 getProxy():JDK代理生成代理对象

2.9.3.4 createProxyClassAndInstance():Objenesis实例化代理对象


一、基本介绍

1.1 核心概念

1.1.1 AOP

AOP(Aspect Oriented Programming):即面向切面编程。抽取共性代码(即通知),植入到待增强的方法(即切入点),其中通知和切入点的关系就是切面

  • 作用:在不改原有代码的前提下对代码进行增强。对于一套已经存在的代码,我们想给它扩展功能,例如需要打印日志,使用AOP后,我们不需要直接改动原代码,而是创建一个新的类,并指定原代码的全限定名、方法名,指定是在方法执行前或执行后执行本段逻辑。这样就降低了耦合性。
  • 面相对象编程的完善:AOP是OOP(Object Oriented Programming,面向对象编程)的补充和完善。传统面向对象编程存在横切关注点(横越多个模块的行)问题,即日志、异常处理等通用业务分散在多个类中,导致代码重复。使用AOP可以将日志逻辑封装成一个独立的切面,统一应用到所有要用的模块。
    • 核心关注点:业务逻辑的核心流程。适合使用OOP实现核心业务的模块化。
    • 横切关注点:与业务无关但必须存在的辅助功能(如日志、权限校验)。适合使用AOP实现统一的辅助。
  • 优势
    • 提高代码可维护性和可扩展性:扩展通用功能时,只需要增加切面,或者修改已有切面的适用范围(切入点)。
    • 减少侵入性:不需要修改原代码逻辑,只需要加一个注解(例如@Transactional)或者创建一个切面类。
  • 缺点
    • 代码可读性变差:本来一个业务逻辑,使用切面后,需要同时看多个切面,可读性就差了一点。
    • 性能稍差:相比直接将逻辑写进原代码里,切面多了一个匹配表达式、反射(JDK动态代理)或操作字节码(CGLIB动态代理)的过程,造成了一点性能开销。所以切面不适用于对性能特别敏感的场景。解决方案是优先使用within()缩小类匹配范围,避免复杂execution表达式。@Pointcut(value = "@within(注解类名)") 
  • 应用场景
    • 日志:统一记录方法入参、返回值、执行时间。
    • 事务:想开启事务,直接方法注解@Transactional
    • 权限校验:在方法执行前验证用户权限。
    • 性能监控:写个切面,对要判断性能的方法打印方法耗时。
    • 接口幂等性:编写一个幂等性的切面和注解,对要防止重复提交的接口加上此注解,防止订单重复提交。

1.1.2 连接点、切面、切入点、通知、顾问

  • 连接点(JoinPoint):可以被增强的方法。它可能已经被增强,也可能还没有被增强。
    • 不允许被增强的方法:例如不是Bean的类里的方法不允许被Spring AOP增强。
  • 切入点(Pointcut):匹配连接点的表达式。
    • 连接点是全部方法,切入点匹配某些需要被增强的方法。连接点范围要比切入点范围大。
    • 是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点。
  • 通知(Advice):要增强的内容,共性的方法。在切入点处执行的操作,也就是共性功能。它是切面类中,带有@Before等注解的方法。
  • 通知类:切面类。
  • 切面(Aspect):描述通知与切入点的对应关系。把通知和切入点绑定到一块,一个通知对应一个切入点。例如切面是Before,即通知在切入点之前运行。
  • 顾问(Advisor):​代表通知和切入点的组成。顾问 = 通知 + 切入点。
  • 目标对象/原始对象:等待被增强的对象
  • 代理对象:被增强后的完全体对象

1.2 代理设计模式 

导航

Java代理模式详解:静态、JDK动态与Cglib代理-优快云博客

代理设计模式(为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象)共有以下三种: 

  • 静态代理:代理对象与目标对象实现或继承相同的接口或父类。例如订单类OrderServiceImpl提交订单方法SubmitOrder(),我们需要修改逻辑,直接继承OrderServiceImpl或者OrderService,然后给新类注解@Primary
    • 优点
      • 简单直接
      • 无侵入性
      • 静态生成:新建的代理类就是完整的代理类,在编译时就已经生成。可以简单直接的看到代码逻辑。
    • 缺点
      • 代码冗余:每个类要创建一个对应的代理类
      • 扩展性差:每个类只能创建一个对应的代理类,仅适合单一增强,多个功能就不适合了
  • JDK动态代理(Spring采用):运行时创建接口的代理实例,基于反射机制。目标对象有实现接口时采用这种代理。
    • 原始和代理对象实现代理接口,简单工厂类通过Proxy.newProxyInstance()返回增强后的代理对象利用Java反射机制在运行时动态地在内存中生成代理对象。Spring AOP采用了JDK动态代理的方式,在运行时动态的创建代理对象来实现增强。
    • 优点
      • 动态生成:编译期间切面类和原类是两个类,在代码运行期才生成完整的代理类
      • 扩展性强:适合符合增强,一个类能用多个切面增强。
    • 缺点
      • 依赖接口:目标类必须实现接口,否则无法代理。
      • 反射性能稍差:方法调用通过反射实现,略慢于直接调用。JDK 8+后有做优化(缓存Method对象、热点方法、访问权限)。
  • CGLib代码生成库动态代理:运行时创建子类代理的实例,基于ASM框架和字节码文件。目标对象没有实现任何接口时采用这种代理。
    • 简单工厂类实现MethodInterceptor接口重写intercept()方法增强,通过Enhancer工具类返回实例。在内存中构建一个子类对象从而实现对目标对象功能扩展。底层是通过使用ASM框架转换字节码并生成新的类。ASM可以直接生成字节码,也可以通过访问现有字节码来修改它。
    • 优点
      • 无需接口:直接操作字节码文件,不用待增强类实现某个接口。
      • 性能高:使用FastClass(预生成高效字节码,直接通过索引访问方法,绕过反射的权限检查和查找过程),比反射要快一些。
    • 缺点
      • 生成速度慢:首次生成代理类需操作字节码,耗时较长(可通过缓存优化)。
      • 不适用于final:final修饰的类和方法,CGLIB动态代理无法增强。

二、源码解析

2.1 环境准备

Spring版本:2.7.13

引入依赖

<spring-boot.version>2.7.13</spring-boot.version>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

 service:

/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 测试Service
 * @Version: 1.0
 */
public interface TestService {
    /**
     * 测试切面
     */
    void test();
}
/**
 * @Author: vince
 * @CreateTime: 2024/10/23
 * @Description: 测试类实现
 * @Version: 1.0
 */
@Component("testService")
public class TestServiceImpl implements TestService {

    @Override
    public void test() {
        System.out.println("执行测试方法....");
    }
}

 切面

/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 测试切面
 * @Version: 1.0
 */
@Component
@Aspect
public class TestAspect {
    /**
     * 定义切入点
     */
    @Pointcut("execution(public * com.example.demo.demos.service.impl.*.*(..)))")
    public void BrokerAspect(){
    }


    @Before("BrokerAspect()")
    public void doBeforeGame(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法开始执行!");
    }

    @After("BrokerAspect()")
    public void doAfterGame(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法执行结束!");
    }


    @AfterReturning(value = "BrokerAspect()",returning = "result")
    public void doAfterReturningGame(JoinPoint jp, Object result){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法返回 = " + result);

    }

    @AfterThrowing(value = "BrokerAspect()",throwing = "e")
    public void doAfterThrowingGame(JoinPoint jp, Exception e){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法异常通知:"+e.toString());
    }

    @Around("BrokerAspect()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }
}

测试类

/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 测试类
 * @Version: 1.0
 */
@SpringBootTest
public class AopTests {
    @Autowired
    private TestService testService;
    @Test
    public void test(){
        testService.test();
    }
}

启动测试类

2.2 initializeBean():初始化Bean和AOP 

2.2.1 doCreateBean()方法:创建Bean的核心逻辑处理方法

首先回顾Bean的创建过程: 

Bean的生命周期:
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程_spring bean加载-优快云博客 

从上文2.6讲doCreateBean()时有提到,doCreateBean()方法的第六步,是初始化Bean和AOP:

上文有提到过,Spring源码中,出现doXxx()就是实际做操作的代码,例如实际创建Bean、实际获取Bean。 

2.2.2 initializeBean():初始化Bean和AOP 

核心流程

这一步中,Spring具体做了以下操作:

  • 初始化bean:调用initializeBean()方法,初始化和aop,通过JDK的Proxy.newProxyInstance()实现动态代理,返回目标对象的代理对象,对Bean进行增强。
    1. 执行所有BeanPostProcessor的初始化前方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessBeforeInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
      1. BeanPostProcessor:Bean前后置处理器。
    2. 初始化:如果Bean实例实现了InitializingBean接口(通过instanceof判断),调用Bean重写的afterPropertiesSet()方法,处理初始化逻辑。afterPropertiesSet译为“在属性填充之后”
    3. 执行所有BeanPostProcessor的初始化后方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。

代码解析

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory  

本方法位于AbstractAutowireCapableBeanFactory类,负责初始化Bean和自动装配。

    /**
     * 初始化给定的Bean实例,应用工厂回调、初始化方法以及Bean后置处理器。
     *
     * <p>该方法由以下两个场景调用:
     * 1. {@link #createBean}:用于传统定义的Bean初始化
     * 2. {@link #initializeBean}:用于已存在的Bean实例重新初始化
     */
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        // 如果启用了安全上下文,则处理安全上下文
        // 安全上下文包括线程的权限信息,是否允许访问或修改文件、系统属性等,可已通过System.setSecurityManager(new SecurityManager());开启
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 如果没有启用安全上下文,则直接调用Aware接口方法注入
            invokeAwareMethods(beanName, bean);
        }

        // 0.创建代理对象:先初始化代理对象为原对象
        Object wrappedBean = bean;
        // 1.执行所有BeanPostProcessor的初始化前方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessBeforeInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
        // 仅当Bean定义非合成(非框架内部生成)时,执行初始化前处理
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 2.初始化:如果Bean实例实现了InitializingBean接口(通过instanceof判断),调用Bean重写的afterPropertiesSet()方法,处理初始化逻辑。
            // afterPropertiesSet译为“在属性填充之后”
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            // 捕获Bean创建异常
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName,
                    "Invocation of init method failed",
                    ex);                                
        }

        // 3.执行所有BeanPostProcessor的初始化后方法:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        // 返回被包装的实例,即代理对象
        return wrappedBean;
    }

  

2.2.3 回顾BeanPostProcessor:Bean前后置处理器

PostProcessor:一种特殊的bean,它可以拦截bean的创建过程,以提供一些额外的处理。PostProcessor的主要作用是在Spring容器初始化bean时,允许我们介入bean的创建过程,以实现一些自定义的逻辑。

作用:

  • 修改bean的定义:通过实现BeanFactoryPostProcessor接口,我们可以在Spring容器加载bean定义之后,但在实例化bean之前,对bean定义进行修改。例如,我们可以修改bean的作用域,或者添加新的属性值。
  • 修改bean的实例:通过实现BeanPostProcessor接口,我们可以在Spring容器实例化bean之后,但在返回bean之前,对bean进行额外的处理。例如,我们可以修改bean的属性,或者返回一个完全不同的bean实例。
  • 处理特定类型的bean:通过实现BeanPostProcessor的子接口,例如InstantiationAwareBeanPostProcessor或DestructionAwareBeanPostProcessor,我们可以在bean实例化之前、之后或销毁之前,对特定类型的bean进行更详细的处理。
  • 处理占位符:通过使用PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer,我们可以在bean定义中使用占位符,并在实例化bean时,用实际的值替换这些占位符。

常见PostProcessor:

  • BeanPostProcessor接口:Bean实例化前后初始化Bean。作用对象是Bean实例。
  • BeanFactoryPostProcessor接口:修改BeanDefinition元数据、修改Bean属性。作用对象是Bean 定义(BeanDefinition)。
  • InstantiationAwareBeanPostProcessor:Bean实例化前后、Bean设置属性前后初始化Bean。在Bean实例化前后、属性填充前调用。
  • DestructionAwareBeanPostProcessor:在 Bean 销毁之前进行自定义操作。作用对象是Bean销毁阶段。
  • MergedBeanDefinitionPostProcessor:在 BeanDefinition 合并之后、Bean 创建之前执行自定义逻辑。(合并BeanDefinition 详见doCreateBean()方法)在Bean 定义合并完成后、Bean 实例化之前调用。

PostProcessor具体可以看下文的“1.4.3.4 后置处理器:PostProcessor”,这里不再赘述:

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程_spring bean加载-优快云博客

2.3 applyBeanPostProcessorsBeforeInitialization():应用所有前置切面

前置切面和后置切面用的一套逻辑,只是执行时机不同,前置切面此处不再赘述,主要展示下文的后置切面。

2.4 applyBeanPostProcessorsAfterInitialization():应用所有后置切面

在上面initializeBean()方法的第三步,执行了applyBeanPostProcessorsAfterInitialization()方法,此方法的作用是执行所有后置切面。

核心流程

  1. 初始化代理对象:先初始化代理对象为原始对象
  2. 后置增强对象:遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。

具体代码

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory   

    /**
     * 应用所有后置切面
     * 遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。
     * 本方法可以通过JDK的Proxy.newProxyInstance()实现动态代理返回目标对象的代理对象。
     * @param existingBean 已完成初始化的原始Bean实例
     * @param beanName     Bean在容器中的名称
     * @return {@link Object }
     * @throws BeansException
     */
    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
        // 1.创建代理对象:先初始化代理对象为原始对象
        Object result = existingBean;
        // 2.遍历所有BeanPostProcessor实现类所在的列表,执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法。
        // 遍历所有BeanPostProcessor实现类所在的列表
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 执行每个BeanPostProcessor对象里的postProcessAfterInitialization()方法,层层增强。
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        // 返回代理对象
        return result;
    }

  

2.5 AbstractAutoProxyCreator类:代理创建器

 AbstractAutoProxyCreator类是Spring AOP的核心类,这个类专门用于代理对象的创建,后文的增强操作基本都在这个类中。

核心方法

  • postProcessAfterInitialization():创建代理对象
  • wrapIfNecessary():符合条件时包装代理对象
  • getAdvicesAndAdvisorsForBean():
  • createProxy():创建代理对象
/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 代理创建器
 * @Version: 1.0
 */
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    // ...
}

2.6 postProcessAfterInitialization():初始化Bean后增强对象 

上面applyBeanPostProcessorsAfterInitialization()方法,第二步遍历了BeanPostProcessors列表,对原始对象进行了增强。

核心流程

  1. 生成缓存key:根据类的class对象和Bean名称,生成唯一的缓存key(唯一标识当前Bean的代理状态,普通Bean的key为name,FactoryBean的key为“&”+name,例如"&userService")
  2. 校验是否已创建过代理对象:判断方法是通过earlyProxyReferences缓存,它记录这个原始对象是否进行了AOP。
  3. 包装代理对象:如果符合条件(即没有被代理过、不是Spring内部基础设施Bean(例如Advice 、Pointcut 类)),将bean包装为代理对象

具体代码

    /**
     * 创建代理对象:在Bean初始化完成后,根据条件创建代理对象。
     * @param bean 原始对象
     * @param beanName Bean名称
     * @return {@link Object }
     */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            // 1.生成缓存key:根据类的class对象和Bean名称,生成唯一的缓存key(唯一标识当前Bean的代理状态)。
            // 普通bean的缓存key为Bean名, FactoryBean(通过实现FactoryBean接口创建的Bean)的缓存键添加"&"前缀(如"&userService"),以防止出现冲突。
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // 2.判断是否已经创建过代理对象:判断方法是通过earlyProxyReferences缓存,它记录这个原始对象是否进行了AOP。具体可以参考getEarlyBeanReference()方法,在三级缓存那篇文章有提到过
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 3.包装代理对象:如果符合条件(即没有被代理过、不是Spring内部基础设施Bean(例如Advice 、Pointcut 类)),将bean包装为代理对象
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        // 3.返回Bean
        return bean;
    }

2.7 wrapIfNecessary():符合条件时包装代理对象  

核心流程

  1. 校验:如果bean已被处理过、是Spring自带基础设施Bean(如Advice 、Pointcut 类)、原始实例,则直接返回
  2. 创建代理对象:调用createProxy()方法,根据bean的所有通知和顾问,创建代理对象
  3. 标记无需代理:创建完后,标记本Bean无需再被代理

具体代码: 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
    /**
     * 在符合条件时将Bean包装为代理对象。
     * @param bean
     * @param beanName
     * @param cacheKey
     * @return {@link Object }
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 1.校验:如果bean已被处理过、是Spring自带Bean的Bean、原始实例,则直接返回
        // 如果bean已被处理过则直接返回。目标源变量targetSourcedBeans专门收集已被处理过的Bean
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 无需代理的bean直接返回。false表示此bean不需要进行Aop
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        // Spring内部基础设施Bean(例如Advice 、Pointcut 类)、需要被跳过的Bean(即原始实例)直接返回
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // 获取当前bean的所有通知和顾问。
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 2.创建代理对象:调用createProxy()方法,根据bean的所有通知和顾问,创建代理对象
            // TargetSource是原始对象来源(属性包括类的class对象、是否是静态类等)
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        // 3.创建完后,标记这个Bean无需再被代理
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

2.8 createProxy():根据通知和顾问创建代理对象

上面wrapIfNecessary()第二步调用了createProxy()方法,这是实际创建代理对象的方法,参数包括类的class对象、Bean名、所有通知和顾问。

核心流程

  1. 暴露目标对象:如果当前BeanFactory是ConfigurableListableBeanFactory,就暴露目标对象。暴露指给Bean定义设置原始对象字节码属性targetClass
  2. 创建和配置代理工厂:创建代理工厂,并将目标对象的属性复制给这个代理工厂
  3. 检查是否指定代理方法:根据属性指定的代理类型(默认JDK动态代理),添加接口到代理工厂或使用CGLIB代理。
    1. CGLIB动态代理:如果强制使用CGLIB动态代理,则添加目标类的所有接口到代理工厂
    2. JDK动态代理:如果强制使用JDK动态代理,则使用默认规则(如果有实现接口则继续使用JDK代理,如果没实现接口则使用CGLIB代理)
  4. 配置代理工厂:给代理工厂设置顾问数组、目标源
  5. 执行用户自定义模板方法:这个类是空方法,供子类扩展
  6. 性能优化:冻结代理工厂,标记代理工厂已预过滤
    1. 冻结代理工厂:冻结后代理工厂不允许再被配置
    2. 标记代理工厂已预过滤:标记后,告诉JDK我已经预检查过了,你运行时不需要再检查了。这样每次方法调用时不需要再重新校验顾问与切入点是否匹配
  7. 生成代理对象:选用合适的类加载器(通过proxyClassLoader属性获取类加载器,默认是应用程序类加载器AppClassLoader),创建代理对象

具体代码: 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator 

    /**
     * 根据通知和顾问创建代理对象:创建AOP代理对象的核心方法
     * @param beanClass         目标Bean的Class对象
     * @param beanName          Bean名称
     * @param specificInterceptors 特定拦截器数组(可能包含Advisor/Advice/Interceptor)
     * @param targetSource      原始对象来源(属性包括类的class对象、是否是静态类等)
     * @return 生成的代理对象
     */
    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                                 @Nullable Object[] specificInterceptors, TargetSource targetSource) {

        // 1.暴露目标对象:如果当前BeanFactory是ConfigurableListableBeanFactory,就暴露目标对象。暴露指给Bean定义设置原始对象字节码属性targetClass
        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            // 暴露:给Bean定义设置原始对象字节码属性targetClass
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        // 2.创建和配置代理工厂:创建代理工厂,并将目标对象的属性复制给这个代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        // 3.检查是否指定代理方法:如果强制使用CGLIB动态代理,则添加目标类的所有接口到代理工厂;如果强制使用JDK动态代理,则使用默认规则(如果有实现接口则继续使用JDK代理,如果没实现接口则使用CGLIB代理)
        // 3.1 如果强制使用CGLIB动态代理,则添加目标类的所有接口到代理工厂
        // ProxyConfig类的proxyTargetClass属性:默认false即强制使用JDK动态代理。本属性可以通过配置类或引导类注解@EnableAspectJAutoProxy(proxyTargetClass = true) 设置为CGLIB动态代理
        if (proxyFactory.isProxyTargetClass()) {
            // 处理目标类已经是JDK代理类或Lambda表达式的情况
            if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
                // 添加目标类的所有接口到代理工厂
                for (Class<?> ifc : beanClass.getInterfaces()) {
                    proxyFactory.addInterface(ifc);
                }
            }
        }
        // 3.2 如果强制使用JDK动态代理,则使用默认规则(如果有实现接口则继续使用JDK代理,如果没实现接口则使用CGLIB代理)
        else {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                // 若存在有效接口 → 使用 JDK 动态代理,并将接口添加到 ProxyFactory。
                // 若无有效接口 → 强制使用 CGLIB 代理(因为JDK代理的要求是目标类必须有实现某个接口,所以如果没实现接口,则使用CGLIB动态代理)。
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        // 4.配置代理工厂:给代理工厂设置顾问数组、目标源
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        // 5.执行用户自定义模板方法:这个类是空方法,供子类扩展
        customizeProxyFactory(proxyFactory);

        // 6.性能优化:冻结代理工厂(冻结后代理工厂不允许再被配置)和标记代理工厂已预过滤(标记后,告诉JDK我已经预检查过了,你运行时不需要再检查了。这样每次方法调用时不需要再重新校验顾问与切入点是否匹配)
        // 6.1 冻结代理工厂:冻结后代理工厂不允许再被配置
        proxyFactory.setFrozen(this.freezeProxy);
        // 6.2 标记代理工厂已预过滤:标记后,告诉JDK我已经预检查过了,你运行时不需要再检查了。这样每次方法调用时不需要再重新校验顾问与切入点是否匹配
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        // 7.生成代理对象:选用合适的类加载器(通过proxyClassLoader属性获取类加载器,默认是应用程序类加载器AppClassLoader),创建代理对象
        // 应用程序类加载器AppClassLoader(最低端):负责加载类路径的所有类库,在大多数情况下,我们编写的 Java 程序都是由这个类加载器加载的。在网上是扩展类加载器ExtClassLoader、启动类扩展器BootStrapClassLoader。
        // 优先使用默认的代理类加载器AppClassLoader
        ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
            classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
        }
        // 生成代理对象
        return proxyFactory.getProxy(classLoader);
    }

2.9 getProxy():生成代理对象

2.9.1 createAopProxy():获取JDK或CGLIB代理实现类

上面createProxy()的最后一步,是调用getProxy()方法,根据类加载器,生成代理对象。

createProxy()算是创建代理对象的最后一个环节,它调用Proxy.newProxyInstance()生成代理对象。

核心流程

  1. 创建aop实现类对象
    1. JDK动态代理实现类:如果目标对象是接口、JDK代理类、Lambda类,则返回JDK动态代理实现类;
    2. CGLIB动态代理实现类:否则返回CGLIB动态代理实现类
  2. 生成代理对象:调用JDK或CGLIB动态代理实现类的生成代理对象方法

具体代码: 

org.springframework.aop.framework.ProxyFactory

ProxyFactory类

专门用于生成代理对象,其中只有构造方法和getProxy()方法。

    /**
     * 生成代理对象
     * @param classLoader 类加载器:默认是应用程序类加载器
     * @return {@link Object }
     */
    public Object getProxy(@Nullable ClassLoader classLoader) {
        // 1.创建aop实现类对象:如果目标对象是接口、JDK代理类、Lambda类,则返回JDK动态代理实现类;否则返回CGLIB动态代理实现类
        // 2.生成代理对象:调用JDK或CGLIB动态代理实现类的生成代理对象方法
        return createAopProxy().getProxy(classLoader);
    }

 org.springframework.aop.framework.ProxyCreatorSupport

ProxyCreatorSupport类

代理生成器支持类。主要负责为不同代理实现(JDK 动态代理、CGLIB)提供统一的创建模板。

    /**
     * 使创建aop实现类对象:如果目标对象是接口、JDK代理类、Lambda类,则返回JDK动态代理实现类;否则返回CGLIB动态代理实现类
     * @return {@link AopProxy }
     */
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // 使用工厂设计模式,创建代理对象
        return getAopProxyFactory().createAopProxy(this);
    }
    /**
     * 创建aop实现类对象:如果目标对象是接口、JDK代理类、Lambda类,则返回JDK动态代理实现类;否则返回CGLIB动态代理实现类
     * @param config
     * @return {@link AopProxy }
     * @throws AopConfigException
     */
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!NativeDetector.inNativeImage() &&
                (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代理类、Lambda类,则返回JDK动态代理实现类;
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            // 否则返回CGLIB动态代理实现类
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

2.9.2 JDK动态代理实现类

2.9.2.1 基本介绍

根据上一节createAopProxy()判定,如果目标对象是接口、JDK代理类、Lambda类,调用的是JDK动态代理实现类JdkDynamicAopProxy的getProxy()方法。

2.9.2.2 JdkDynamicAopProxy类:JDK动态代理实现类

JDK动态代理实现类是final类,不可被继承,代表作者不想其他人重写这个类。 它实现了AopProxy接口。AopProxy接口是代理生成的统一接口,一切JDK动态代理实现类、CGLIB动态代理实现类都实现了这个接口。

/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: JDK动态代理实现类:final类不可被继承,代表作者不想其他人重写这个类。
 * 另外,CGLIB动态代理实现类不是final类,它有子类ObjenesisCglibAopProxy,集成了Objenesis,可以绕过构造方法实例化对象
 * @Version: 1.0
 */
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    // getProxy()等方法...
}
/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 代理生成的统一接口,JDK动态代理实现类、CGLIB动态代理实现类都实现了这个接口。
 * @Version: 1.0
 */
public interface AopProxy {
    // getProxy()等方法...
}
2.9.2.3 getProxy():JDK代理生成代理对象

核心流程

  1. 实例化代理对象:使用JDK的静态方法Proxy.newProxyInstance(),基于反射实例化代理对象

具体代码

org.springframework.aop.framework.JdkDynamicAopProxy
    /**
     * JDK动态代理生成代理对象
     * @param classLoader
     * @return {@link Object }
     */
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        // 打印trace级别日志
        // Trace级别是日志框架(如Logback、Log4j)中最低的日志级别,其详细程度高于DEBUG,用于追踪程序执行路径中的每一个步骤。
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        // 1.实例化代理对象:使用Proxy.newProxyInstance()静态方法,基于反射实例化代理对象
        return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this);
    }

2.9.2.4 Proxy.newProxyInstance():JDK源码实例化代理类

核心流程

  1. 校验参数非空
  2. 克隆接口数组:浅拷贝(只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存。)接口数组,防止实例化过程中,接口被篡改
  3. 校验权限:通过安全管理器,校验是否有权创建代理对象
  4. 获取代理类的class对象:根据类加载器和接口数组,获取代理类的class对象(优先从缓存中获取,如果没查到则调用ProxyGenerator.generateProxyClass()生成字节码文件byte数组,然后调用ClassLoader.defineClass()将字节码转换为Class对象。)
  5. 基于反射实例化代理类:根据代理类的class对象,基于反射先获取构造器对象,然后调用newInstance()实例化代理类

具体代码

    /**
     * 基于反射实例化代理对象:JDK内部创建代理对象的方法。
     * @param loader 类加载器
     * @param interfaces 接口数组
     * @param h 方法调用的统一处理逻辑
     * @return {@link Object }
     * @throws IllegalArgumentException
     */
    // Proxy类是JDK内部类。@CallerSensitive标记方法对调用者敏感,需进行安全检查。
    // jdk内有些方法,jvm的开发者认为这些方法危险,不希望开发者调用,就把这种危险的方法用 @CallerSensitive修饰,用于防止双重反射攻击。
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
            throws IllegalArgumentException
    {
        // 1.校验参数非空
        // 处理器不可为空
        Objects.requireNonNull(h);

        // 2.克隆接口数组:浅拷贝(只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存。)接口数组,防止实例化过程中,接口被篡改
        final Class<?>[] intfs = interfaces.clone();
        // 3.校验权限:通过安全管理器,校验是否有权创建代理对象
        // 获取安全管理器实例
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // 校验是否有权创建指定类加载器和接口的代理类
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        // 4.获取代理类的class对象:根据类加载器和接口数组,获取代理类的class对象(优先从缓存中获取,如果没查到则调用ProxyGenerator.generateProxyClass()生成字节码文件byte数组,然后调用ClassLoader.defineClass()将字节码转换为Class对象。)
        Class<?> cl = getProxyClass0(loader, intfs);

        // 5.基于反射实例化代理类:根据代理类的class对象,基于反射先获取构造器对象,然后调用newInstance()实例化代理类
        try {
            if (sm != null) {
                // 校验权限:校验是否有实例化此代理类的权限
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            // 获取构造器对象:基于反射,获取构造器对象
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            // 突破构造器private访问限制(若代理类是非public的)
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            // 实例化代理类:基于反射,通过构造器实例化代理类
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

    /**
     * 获取代理类的class对象
     * @param loader
     * @param interfaces
     * @return {@link Class }<{@link ? }>
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        // 接口数量校验:JVM规范接口数由u2类型存储,数量不能超过65535
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // 从缓存获取或创建代理类(线程安全,避免重复生成)
        // 获取代理类的class对象:根据类加载器和接口数组,获取代理类的class对象(优先从缓存中获取,如果没查到则调用ProxyGenerator.generateProxyClass()生成字节码文件byte数组,然后调用ClassLoader.defineClass()将字节码转换为Class对象。)
        return proxyClassCache.get(loader, interfaces);
    }

2.9.3 CGLIB动态代理实现类

2.9.3.1 基本介绍

根据上一节createAopProxy()判定,如果目标对象不是接口、JDK代理类、Lambda类,调用的是CGLIB动态代理实现类ObjenesisCglibAopProxy的getProxy()方法。

2.9.3.2 ObjenesisCglibAopProxy类: 集成Objenesis的CGLIB代理实现类

集成Objenesis 库的CGLIB动态代理实现类,可以绕过构造器直接实例化对象,解决目标类无默认构造器或构造器调用存在副作用时的代理实例化问题。

这个类只有一个方法,即createProxyClassAndInstance(),用于实例化代理类。对于getProxy()等其他方法,主要继承它的父类CglibAopProxy

/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 集成Objenesis 库的CGLIB动态代理实现类
 * 父类CglibAopProxy:CGLIB动态代理的基础实现类
 * @Version: 1.0
 */
class ObjenesisCglibAopProxy extends CglibAopProxy {
    /**
     * 实例化代理类:使用Objenesis库或反射机制,实例化代理对象
      * 本类只有这一个普通方法,本类目的就是通过Objenesis或反射实例化代理对象
     * @param enhancer
     * @param callbacks
     * @return {@link Object }
     */
    @Override
    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
        // ...
    }
}

父类CglibAopProxy类

CGLIB动态代理的基础实现类,它实现了AopProxy接口。AopProxy接口是代理生成的统一接口,一切JDK动态代理实现类、CGLIB动态代理实现类都实现了这个接口。

/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: CGLIB动态代理的基础实现类
 * 父接口:AopProxy,代理生成的统一接口,所有JDK动态代理实现类、CGLIB动态代理实现类都实现了这个接口。
 * @Version: 1.0
 */
class CglibAopProxy implements AopProxy, Serializable {
    // getProxy()等方法...
}
/**
 * @Author: vince
 * @CreateTime: 2025/03/17
 * @Description: 代理生成的统一接口,所有JDK动态代理实现类、CGLIB动态代理实现类都实现了这个接口。
 * @Version: 1.0
 */
public interface AopProxy {
    // getProxy()等方法...
}

2.9.3.3 getProxy():JDK代理生成代理对象

核心流程

  1. 检测添加父类所有接口:如果类名是否包含CGLIB标识符(如 $$EnhancerBySpringCGLIB$$),则给通知类变量添加父类实现的所有接口
  2. final校验:校验目标类和方法是否是final,如果是则不允许创建CGLIB动态代理,抛出异常
  3. 创建配置增强器Enhancer:创建Enhancer并设置类加载器(默认是最底层的应用程序类加载器)、父类、接口、命名测量、类加载器生成策略、回调对象数组、回调过滤器
    1. 回调对象数组:包括增强方法(advisors属性包含了目标对象的所有AOP切面)、目标方法、无操作、静态目标方法、Advised接口方法、equals方法、hashCode方法等回调对象。
  4. 实例化代理类:使用Objenesis库或反射机制,实例化代理对象

具体代码

org.springframework.aop.framework.CglibAopProxy
    /**
     * CGLIB动态代理生成代理对象
     * 本方法是ObjenesisCglibAopProxy的父类,CglibAopProxy中的方法
     * @param classLoader
     * @return {@link Object }
     */
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        // 打印日志:正在创建CGLIB动态代理对象+目标对象。
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
        }

        try {
            // 获取目标对象的class对象
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            // 1.检测添加父类所有接口:如果类名是否包含CGLIB标识符(如 $$EnhancerBySpringCGLIB$$),则给通知类变量添加父类实现的所有接口
            if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                // 获取父类的class对象
                proxySuperClass = rootClass.getSuperclass();
                // 给通知类变量添加父类实现的所有接口
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // 2.final校验:校验目标类和方法是否是final,如果是则不允许创建CGLIB动态代理,抛出异常
            validateClassIfNecessary(proxySuperClass, classLoader);

            // 3.创建配置增强器Enhancer:创建Enhancer并设置类加载器(默认是最底层的应用程序类加载器)、父类、接口、命名测量、类加载器生成策略、回调对象数组、回调过滤器
            Enhancer enhancer = createEnhancer();
            // 创建Enhancer实例
            if (classLoader != null) {
                // 设置类加载器(默认是最底层的应用程序类加载器)
                enhancer.setClassLoader(classLoader);
                // 处理热部署场景:当使用SmartClassLoader且类可重载时,禁用字节码缓存
                // SmartClassLoader:Spring自带的类加载器,在开发环境中支持热部署(例如springboot项目加入DevTools依赖,在修改代码后无需重启,点击构建即可生效代码改动)和快速应用重启
                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 ClassLoaderAwareGeneratorStrategy(classLoader));

            // 构建回调对象数组:回调数组包括增强方法、目标方法、无操作、静态目标方法、Advised接口方法、equals方法、hashCode方法等回调对象
            // 回调对象aopInterceptor的advisors属性包含了目标对象的所有AOP切面
            /**
             * 回调数组包含以下元素:
             * Callback[] mainCallbacks = new Callback[] {
             *     aopInterceptor,        // 处理增强方法(AOP逻辑)
             *     targetInterceptor,    // 直接调用目标方法(未增强但需代理暴露)
             *     new SerializableNoOp(), // 占位符(无操作)
             *     targetDispatcher,      // 处理未增强的静态目标方法
             *     this.advisedDispatcher, // 处理Advised接口方法(如addAdvisor)
             *     new EqualsInterceptor(this.advised),  // 代理equals方法
             *     new HashCodeInterceptor(this.advised) // 代理hashCode方法
             * };
             */
            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 CglibAopProxy.ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // 4.实例化代理类:使用Objenesis库或反射机制,实例化代理对象
            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) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

2.9.3.4 createProxyClassAndInstance():Objenesis实例化代理对象

上面getProxy()方法,最后一步调用了createProxyClassAndInstance()方法,这个方法是CGLIB最终实例化代理对象的方法。它先尝试通过Objenesis库绕过构造器实例化对象,如果失败则使用常规的反射方法获取构造器对象后实例化。

核心流程

  1. 获取Class对象:获取代理类的Class对象
  2. 尝试Objenesis实例化:尝试Objenesis,绕过构造器实例化代理对象。
    1. Objenesis:一个绕过构造函数实例化对象的库。由于绕过了构造方法,所以无法调用构造方法中的初始化逻辑。
  3. 基于反射实例化:Objenesis失败时,通过反射获取构造器对象,传入构造参数,实例化代理对象
  4. 设置回调数组:将回调对象数组作为参数,设置给代理对象
  5. 返回代理对象:返回实例化后的代理对象

具体代码

org.springframework.aop.framework.ObjenesisCglibAopProxy 

    /**
     * 实例化代理类:使用Objenesis库或反射机制,实例化代理对象
     * @param enhancer
     * @param callbacks
     * @return {@link Object }
     */
    @Override
    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
        // 1:获取代理类的class对象
        Class<?> proxyClass = enhancer.createClass();
        Object proxyInstance = null;

        // 2:尝试Objenesis,绕过构造器实例化代理对象
        if (objenesis.isWorthTrying()) {
            try {
                // Objenesis黑科技:一个绕过构造函数实例化对象的库。由于绕过了构造方法,所以无法调用构造方法中的初始化逻辑。
                proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
            }
            catch (Throwable ex) {
                logger.debug("Unable to instantiate proxy using Objenesis, " +
                        "falling back to regular proxy construction", ex);
            }
        }

        // 3:基于反射实例化:Objenesis失败时,通过反射获取构造器对象,传入构造参数,实例化代理对象
        if (proxyInstance == null) {
            try {
                // 根据是否传入构造参数选择构造器
                Constructor<?> ctor = (this.constructorArgs != null ?
                        proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
                        proxyClass.getDeclaredConstructor());
                // 开启这个属性可以突破private构造方法限制
                ReflectionUtils.makeAccessible(ctor);
                // 通过构造器对象,实例化对象(可能触发构造方法逻辑)
                proxyInstance = (this.constructorArgs != null ?
                        ctor.newInstance(this.constructorArgs) : ctor.newInstance());
            }
            catch (Throwable ex) {
                throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
                        "and regular proxy instantiation via default constructor fails as well", ex);
            }
        }

        // 4:将回调对象数组作为参数,设置给代理对象
        ((Factory) proxyInstance).setCallbacks(callbacks);
        // 5.返回实例化后的代理对象
        return proxyInstance;
    }

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小海绵【vincewm】

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值