spring aop代码的增强

简介: 这篇博客,主要会分析spring aop是如何实现代码增强的。从上一篇博客 我们大概知道,spring能在不改变代码的前提下,往一个方法的之前和之后添加代码。

这篇博客,主要会分析spring aop是如何实现代码增强的。

上一篇博客 我们大概知道,spring能在不改变代码的前提下,往一个方法的之前和之后添加代码。

想下,java中有哪种技术可以帮我们实现动态修改代码呢?就是jdk的动态代理。关于动态代理可以看下这篇博客jdk动态代理与cglib动态代理实现原理

大体我们先知道,jdk动态代理和cglib的动态代理都可以在运行时修改源码。两者之间的基本区别之一是,jdk动态代理需要被代理的类实现接口,cglib不需要。

然后我们开始分析spring是如何使用动态代理的。

img_0594ffd5776fbada213fd874fb7627b3.png

回到spring调用链的图,spring 对于aop的增强是在创建bean时,通过BeanPostProcessor机制来实现的。在spring初始化之后类后,会有一次对类增强的机会。就是在AbstractAutoProxyCreator里。

AbstractAutoProxyCreator.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;
}

这里就是检查下该类是否已经暴露过了(可能已经创建了,比如A依赖B时,创建A时候,就会先去创建B。当真正需要创建B时,就没必要再代理一次已经代理过的对象)

wrapIfNecessary

真正创建代理对象的地方就在wrapIfNecessary


img_84dfd03c42fdf1fa2ee6fae79de9e3c9.png

依旧我们先来看最关键的一步,createProxy

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);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    for (Advisor advisor : advisors) {
        proxyFactory.addAdvisor(advisor);
    }

    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    //获取代理对象
    return proxyFactory.getProxy(getProxyClassLoader());
}

createProxy也很长,依旧我们只关心最重要的也就是最后一行,proxyFactory.getProxy

整理了一个流程图


img_2589a193b2e6147024a77ffb39dbd680.png

大概说明下:
1)代理对象的创建最终委托给AopProxy生成
2)AopProxy的创建交由AopProxyFactory工厂
3)AopProxyFactory的默认实现是DefaultAopProxyFactory

AopProxyFactory.createAopProxy

那么我们先来看看AopProxy究竟是如何创建的。

img_b516f3a5c584ce53d2ae23d45e912fa4.png

我们首先可以看出,最后生成的AopProxy底层实现要么是cglib的,要么是jdk。再然后,我们分析下,什么时候使用jdk动态代理,什么时候使用cglib的。

1)配置了optimize。由于 cglib的动态代理创建类比较慢,但是执行代码比较快,jdk动态代理相反,创建比较快,执行比较慢。如果配置了optimize=true,那么目标类实现了接口就使用jdk代理,否则就用cglib。默认是false。
2)proxyTargetClass 是否强制使用cglib实现代理。默认是false
3)没有可代理的接口

代理对象的生成

到了这里,我们继续分析AopProxy如何生成代理对象(这里以jdk动态代理来分析)


img_07717fd9e978773fb0e3cbd468f87bf0.png

看到Proxy.newProxyInstance就非常熟悉了,jdk的动态代理。

总结及待续

这篇博客大致分析了下,spring是如何创建代理对象的。jdk及cglib代理方式的选择。以及大概看了下jdk代理对象的创建。

当然还是留了很多问题,首先就是wrapIfNecessary里的各种缓存究竟是干啥用的,再然后就是jdk代理里,非常核心的InvocationHandler.invoke方法是如何实现的。再然后,我们常说的,切面,通知这些概念在源码层究竟对应着啥。这些问题会再下一篇博客介绍。

目录
相关文章
|
4天前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
17天前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
15 0
Spring高手之路22——AOP切面类的封装与解析
|
17天前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
30 0
|
17天前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
20 0
|
19天前
|
监控 安全 Java
【开发者必备】Spring Boot中自定义注解与处理器的神奇魔力:一键解锁代码新高度!
【8月更文挑战第29天】本文介绍如何在Spring Boot中利用自定义注解与处理器增强应用功能。通过定义如`@CustomProcessor`注解并结合`BeanPostProcessor`实现特定逻辑处理,如业务逻辑封装、配置管理及元数据分析等,从而提升代码整洁度与可维护性。文章详细展示了从注解定义、处理器编写到实际应用的具体步骤,并提供了实战案例,帮助开发者更好地理解和运用这一强大特性,以实现代码的高效组织与优化。
30 0
|
19天前
|
Java 开发者 Spring
Spring Boot大法好:解耦、隔离、异步,让代码‘活’起来,性能飙升的秘密武器!
【8月更文挑战第29天】解耦、隔离与异步是Spring Boot中的关键设计原则,能大幅提升软件的可维护性、扩展性和性能。本文通过示例代码详细探讨了这些原则的应用:依赖注入和面向接口编程实现解耦;模块化设计与配置文件实现隔离;`@Async`注解和`CompletableFuture`实现异步处理。综合运用这些原则,可以显著提升软件质量和性能,使系统更加健壮、灵活和高效。
22 0
|
26天前
|
缓存 安全 Java
Spring AOP 中两种代理类型的限制
【8月更文挑战第22天】
13 0
|
26天前
|
Java Spring
|
4月前
|
安全 Java Spring
Spring之Aop的底层原理
Spring之Aop的底层原理
|
4月前
|
设计模式 Java uml
Spring AOP 原理
Spring AOP 原理
28 0