Spring之AOP

AOP介绍及优缺点

AOP(‌面向切面编程)‌是一种编程范式,‌它允许开发者在不修改现有代码的情况下,‌通过定义“切面”来横切多个模块,‌从而实现对这些模块的某些行为进行统一管理和控制。‌‌ AOP的核心概念包括切面(‌Aspect)‌、‌连接点(‌Join point)‌、‌通知(‌Advice)‌和切点(‌Pointcut)‌。‌

横切关注点:跨越应用程序多个模块的方法和功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。例如,‌事务管理、‌日志记录、‌权限控制、性能监控等都可以看作是横切关注点。‌

  • 切面‌:横切关注点 被模块化 的特殊对象。即,它是一个类。‌
  • 连接点‌:‌在程序执行过程中某个特定的点,‌如方法调用或异常处理时。‌在Spring AOP中,‌一个连接点总是代表一个方法的执行。‌
  • 通知‌:‌在切面的某个特定的连接点上执行的动作。‌通知有多种类型,‌包括“around”、‌“before”和“after”等,‌它们定义了在连接点上应该执行的具体操作。‌
  • 切点‌:‌匹配连接点的断言。‌通知和切点表达式相关联,‌并在满足这个切点的连接点上运行。‌

AOP的主要优点包括:‌

  1. 代码模块化:将横切关注点从业务逻辑中分离,使代码结构更清晰,模块划分更合理。例如,将日志记录、权限控制等与业务无关的功能独立出来,业务代码更专注于核心业务。
  2. 提高代码复用性:横切关注点的代码可以在多个地方重复使用,无需在每个相关位置重复编写。比如,一个通用的事务处理逻辑可以应用于多个业务方法。
  3. 增强可维护性:当横切关注点的逻辑需要修改时,只需在切面中进行修改,而不必在众多的业务方法中逐一修改。

AOP 技术的缺点:

  1. 增加复杂性:对于初次接触和理解的开发者来说,AOP 的概念和实现机制可能较为复杂,增加了学习成本。
  2. 调试困难:由于横切逻辑的织入是在运行时动态进行的,可能会增加调试的难度,特别是在出现问题时定位和排查故障。

aop的实现原理

AOP的实现原理通常依赖于动态代理技术。动态代理技术可以分为两类:基于接口的动态代理和基于类的动态代理。

  • 基于接口的动态代理:通过Java的java.lang.reflect.Proxy类和InvocationHandler接口实现。

  • 基于类的动态代理:通常使用第三方库,如CGLIB,它通过继承的方式在运行时创建代理类。

AOP利用动态代理的设计模式。

AOP底层默认jdk动态代理,如果没有接口使用cglib动态代理。

应用场景
常用于日志记录,性能统计,安全控制,事务处理,异常处理等等。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代理模式的分类

为什么要学习代理模式?因为这就是SpringAop的底层!

静态代理

在这里插入图片描述
角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人
package com.lx.pojo;

// 租房
public interface Rent {
   
   

    // 出租
    void rent();
    
}



package com.lx.pojo;

// 房东,往外租房子
public class Landlord implements Rent {
   
   


    @Override
    public void rent() {
   
   
        System.out.println("房东要出租房子");
    }
}



// 到这儿,我们就找到房子了
// 然而现实情况是很难直接找到房东,通常都是通过中介来租房子
package com.lx.pojo;

public class Client {
   
   
    public static void main(String[] args) {
   
   
        Landlord landlord = new Landlord();
        // 房东要出租房子
        landlord.rent();
    }
}




package com.lx.pojo;

public class Client {
   
   
    public static void main(String[] args) {
   
   
        Landlord landlord = new Landlord();
        Proxy proxy = new Proxy(landlord);
        // 通过代理找到 房东要出租房子
        // 代理,中介帮房东租房子,但是代理角色一般会有一些附属操作
        proxy.rent();
    }
}

// 通过代理不仅可以帮房东租房子,还可以做很多其他的附属操作
package com.lx.pojo;

public class Proxy implements Rent {
   
   

    private Landlord landlord;

    public Proxy() {
   
   
    }

    public Proxy(Landlord landlord) {
   
   
        this.landlord = landlord;
    }

    @Override
    public void rent() {
   
   
        seeHouse();
        landlord.rent();
        fare();
        signContract();
    }


    // 看房
    // 这个只有中介能做,房东只有几套房子,而中介会有很多房子
    public void seeHouse(){
   
   
        System.out.println("中介带你看房");
    }


    // 收中介费
    public void fare(){
   
   
        System.out.println("收中介费");
    }

    // 签租赁合同
    public void signContract(){
   
   
        System.out.println("签合同");
    }

}

代理模式的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
  • 公共业务就交给代理角色!实现了业务的分工
  • 公共业务发生拓展的时候,方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色。代码量会翻倍,开发效率会变低

静态代理的第二个例子

package com.lx.service;

public interface UserService {
   
   

    void add();
    void delete();
    void update();
    void query();
}




package com.lx.service;

public class UserServiceImpl implements UserService{
   
   
    @Override
    public void add() {
   
   
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
   
   
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
   
   
        System.out.println("修改了一个用户");
    }

    @Override
    public void query() {
   
   
        System.out.println("查询了一个用户");
    }
}



package com.lx.service;

import java.time.LocalDateTime;

public class UserServiceProxy implements UserService{
   
   

    private UserServiceImpl userServiceImpl;

    public UserServiceProxy() {
   
   
    }

    public UserServiceProxy(UserServiceImpl userServiceImpl) {
   
   
        this.userServiceImpl = userServiceImpl;
    }

    @Override
    public void add() {
   
   
        getLocalDateTime();
        userServiceImpl.add();
    }

    @Override
    public void delete() {
   
   
        getLocalDateTime();
        userServiceImpl.delete();
    }

    @Override
    public void update() {
   
   
        getLocalDateTime();
        userServiceImpl.update();
    }

    @Override
    public void query() {
   
   
        getLocalDateTime();
        userServiceImpl.query();
    }


    // 现在增加一个日志功能,检测方法是什么时间开始执行的
    public void getLocalDateTime(){
   
   
        System.out.println(LocalDateTime.now());
    }
}



// 如果要增加日志功能可以在impl中直接添加代码
// 但是改动原有的业务代码,在公司中是大忌
// 我们就可以用代理来实现
package com.lx.pojo;

import com.lx.service.UserServiceImpl;
import com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值