【Spring 从0开始】什么是 AOP?底层原理是?

简介: 【Spring 从0开始】什么是 AOP?底层原理是?

一、什么是 AOP


AOP 就是面向切面编程,是 OOP(面向对象编程)的延续。


利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序可用性,同时也提高了开发效率。


通俗一点说,不用修改原代码,可以给原代码增加新的功能。


二、AOP 底层原理


AOP 底层原理是使用动态代理。


那代理是什么?有动态代理,那是不是还有静态代理?


1. 什么是代理?


就是为一个目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。使用代理对象,是为了在不修改目标对象的基础上,增强目标对象的业务逻辑。


比如目标对象 A,代理对象是 B。


  • 那么现在 B 对 A 进行引用,可以实现 A 有的功能。
  • 另外,B 还可以在自身进行一些新功能,最终不需要修改目标对象 A 。


而代理分为静态代理动态代理区别是:


  • 静态代理有真实的代理类存在,就是我们会代码中创建一个代理类,并在代理类的方法中调用目标对象的方法,以此来完成代理的工作。
  • 动态代理的代理类没有在代码中创建一个代理类,而是在运行时在JVM里面创建代理对象。


2. 什么是静态代理


静态代理是有实实在在的代理类存在,并且和目标类实现相同的接口。


比如,有一个转账业务,现在希望给它增加功能,使在转账之前确认转账人身份,以及转账之后通知收款人。


(1) 接口 AccountServiceDao :


package com.pingguo.spring5.dao;
public interface AccountServiceDao {
    // 主业务逻辑,转账
    void transfer();
}


(2) 接口 AccountServiceDao 的实现类:


package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
    @Override
    public void transfer() {
        System.out.println("调用dao层,完成转账主业务.");
    }
}


(3) 代理类 AccountProxy :


package com.pingguo.spring5.proxy;
import com.pingguo.spring5.dao.AccountServiceDao;
public class AccountProxy implements AccountServiceDao {
    // 目标对象
    private AccountServiceDao target;
    public AccountProxy(AccountServiceDao target) {
        this.target = target;
    }
    /**
     *  代理方法,实现对目标方法的增强
     */
    @Override
    public void transfer() {
        before();
        target.transfer();
        after();
    }
    /**
     *  增强的功能,转账之前使用
     */
    private void before() {
        System.out.println("对转账人身份进行验证.");
    }
    /**
     *  增强的功能,转账之后使用
     */
    private void after() {
        System.out.println("转账完成,已通知收款人.");
    }
}


在代理类中:


  • 添加了添加了目标对象,并且有参构造方法里需要传入目标对象。
  • 代理方法里,调用了目标对象里的转账方法 target.transfer()。
  • before() 和 after() 则是 2个增强的方法,分别作用于 target.transfer() 的前面和后面。


(4) 运行测试


新建一个测试方法,运行看下结果:


@Test
    public void testProxy() {
        // 创建目标对象
        AccountServiceDao target = new AccountServiceImpl();
        // 创建代理对象
        AccountProxy proxy = new AccountProxy(target);
        proxy.transfer();
    }


  • 这里先创建了目标对象
  • 再创建代理对象,并且把目标对象传入
  • 最后调用代理对象里的,被增强过的方法 transfer()。


结果:


对转账人身份进行验证.
调用dao层,完成转账主业务.
转账完成,已通知收款人.
Process finished with exit code 0


优点


  • 效率高,因为所有的类都是已经编写完成的,使用的时候只需要取得代理对象并且执行即可。
  • 同时也可以实现对目标对象中指定的方法进行增强。


缺点


  • 与目标类实现相同的接口代码,冗余。
  • 如果接口发生改变,代理类中的方法也要修改。
  • 代理类服务于一种类型的对象,如果要服务多类型的对象,那么要为每种类型的对象都生成代理类。


3. 什么是动态代理


与静态代理的硬编码方式相比,动态代理支持运行时动态生成代理对象这种方式。换句话说,动态代理并不存在代理类,代理对象直接由代理生成工具动态生成。


优点


  • 用很少的代码对一个类的所有方法实现一样的增强效果。
  • 在编码时,代理逻辑与业务逻辑互相独立,各不影响,减少侵入,降低耦合。


缺点


  • 相对于静态代理,它不能增强其中的某一个方法。

对于动态代理,针对于是否存在接口的情况下,又分为 2 种:

  • 有接口的情况下,使用 JDK 动态代理。
  • 无接口的情况下,使用 CGLIB 动态代理。


使用 JDK 动态代理


使用 JDK 动态代理,创建的是接口实现类的代理对象,以此来实现功能增强。


现在不需要上面创建过的实际代理类了 。


接口,为了后面的一些知识点的说明,里面加个参数,转账的金额:


package com.pingguo.spring5.dao;
public interface AccountServiceDao {
    // 主业务逻辑,转账
    void transfer(int amount);
}


实现类:


package com.pingguo.spring5.dao;
public class AccountServiceImpl implements AccountServiceDao {
    @Override
    public void transfer(int amount) {
        System.out.println("调用dao层,完成转账主业务.金额:" + amount);
    }
}


在测试方法里,直接使用动态代理:


@Test
    public void testDynamicProxy() {
        // 创建目标对象
        AccountServiceDao target = new AccountServiceImpl();
        // 创建代理对象
        AccountServiceDao proxy = (AccountServiceDao) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),  // 目标类使用的类加载器
                target.getClass().getInterfaces(),  // 目标类实现的接口
                new InvocationHandler() {  // 调用处理器
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("对转账人身份进行验证.");
                        Object res =  method.invoke(target, args);
                        System.out.println("转账完成,已通知收款人.");
                        return res;
                    }
                }
        );
        // 让代理工作
        proxy.transfer(10000);
    }


运行结果:


对转账人身份进行验证.
调用dao层,完成转账主业务.金额:10000
转账完成,已通知收款人.
Process finished with exit code 0


动态代理的过程:


  • 创建处理器 InvocationHandler实例。
  • 在调用目标对象时,会调用代理对象。
  • 代理对象去请求目标对象。invoke 方法就是调用目标对象的方法生成代理对象的过程。
  • 同时,在 invoke 方法中进行功能增强。


对于 invoke 中的 3 个参数,分别是:


  • Object proxy:代理对象,一般不会使用。
  • Method method:外面的代理对象调用的方法引用,这里引用的就是 transfer()
  • Object[] args:外面的代理对象调用的方法里面的参数,这里就是参数 amount。


使用 CGLIB 动态代理


CGLIB动态代理的原理是生成目标类的子类,这个子类对象就是代理对象,代理对象是被增强过的。


注意,不管有没有接口都可以使用 CGLIB 动态代理, 而不是只有在无接口的情况下才能使用。


示例就暂时不放了,因为我本地环境问题,有个报错始终未解决,后续再说,不影响继续学习 spring。

相关文章
|
4天前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
|
2月前
|
XML Java 开发者
Spring Boot开箱即用可插拔实现过程演练与原理剖析
【11月更文挑战第20天】Spring Boot是一个基于Spring框架的项目,其设计目的是简化Spring应用的初始搭建以及开发过程。Spring Boot通过提供约定优于配置的理念,减少了大量的XML配置和手动设置,使得开发者能够更专注于业务逻辑的实现。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,为开发者提供一个全面的理解。
47 0
|
13天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
55 8
|
1月前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
104 14
|
2月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
2月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
96 5
|
2月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
91 8
|
2月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
2月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
53 5
|
2月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
56 4