5.2(Spring)AOP

AOP(面向切面)

(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得
业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

AOP解析

AOP 底层使用动态代理
有两种情况动态代理
第一种 有接口情况,使用 JDK 动态代理
创建接口实现类代理对象,增强类的方法

在这里插入图片描述

第二种 没有接口情况,使用 CGLIB 动态代理
创建子类的代理对象,增强类的方法

在这里插入图片描述

JDK动态代理

使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象

Proxy类负责动态创建代理类及其实例

返回值方法名描述
Static ObjectnewProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)返回一个实现了指定接口的代理类实例 对接口方法的调用会被指定的调用处程序参数Interfaces是需要进行代理的接口类型,参数h是接口处理方法的调用处理程序,类加载器loader用来加载动态生成的代理类

InvocationHandler接口是代理方法调用处理程序,负责为代理方法提供业务逻辑,接口中的方法

返回类型方法名描述
Objectinvoke(Obejct proxy,Method method,Object[] args)用于在代理实例上处理方法调用并返回结果 代理对象实现自抽象主题接口,调用代理对象中的接口方法会执行InvocationHandler的invoke方法

JDK动态代理是面向接口的代理实现

所以要求被代理的目标对象必须通过抽象主题接口进行定义,否则无法实施代理

在这里插入图片描述

AOP相当于代理模式

但是代码的操作比起上面两种动态代理简化了很多

AOP术语

连接点

类里面哪些方法,可以被增强,这些方法都成为连接点

正常一个类中的所有方法都可以称之为连接点

切入点

实际被真正增强的方法。成为切入点

首先是本身是连接点,还没有被增强时候称之为连接点,已经被增强了就称之为切入点

通知(增强)

实际增强的业务逻辑部分。在切入点的前后等地方可以动态的添加新功能

通知有多种类型

  1. 前置通知(before):在目标方法执行之前执行

  2. 后置通知(after):在目标方执行完成后执行,如果目标方法异常,则后置通知不再执行

  3. 异常通知(After-throwing):目标方法抛出异常的时候执行

  4. 最终通知(finally);不管目标方法是否有异常都会执行,相当于try。。catch。。finally中的finally

  5. 环绕通知 :相当于将上面几种通知进行一个整合处理

切面

把通知应用到切入点过程

AOP注解操作

因为在实际中并不是使用到XML配置的形式。所以这里我就不多介绍了

Spring 框架一般都是基于 AspectJ 实现 AOP 操作
AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,进行 AOP 操作
基于 AspectJ 实现 AOP 操作
(1)基于 xml 配置文件实现
(2)基于注解方式实现(使用)

引入AOP依赖

 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

切入点表达式

切入点表达式作用:知道对哪个类里面的哪个方法进行增强
语法结构: execution([权限修饰符] [返回类型] [类全路径] 方法名称 )

举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强
execution(* com.atguigu.dao.BookDao.add(..))
举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
execution(* com.atguigu.dao.BookDao.* (..))
举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.*.* (..))

示例

创建一个类,作为主要功能方法
//使用业务逻辑类作为主要的功能
@Component("serviceimple")
public class ServiceImple {

//    在该类中进行打印表示该函数的主要功能
    public void MainMethod(int num){
        System.out.println("开始执行主函数");
//        如果输入的数字大于10抛出异常
            if(num>10){
                throw new IndexOutOfBoundsException();
            }
    }

}
创建增强类
//表示该类加入Spring容器中
@Component
//表示使用动态代理完成AOP
@Aspect
public class SMethod {

//    前置增强,在主方法执行前执行
    @Before(value = "execution(* cn.service.ServiceImple.MainMethod(..))")
    public void beforeMethod(){
        System.out.println("作为前置增强处理");
    }


//    后置增强:在没有异常的时候正常执行
    @AfterReturning(value = "execution(* cn.service.ServiceImple.MainMethod(..))")
    public void AfterReturningMethod(){
        System.out.println("作为后置增强处理");
    }

    //    异常增强:当出现异常会执行的增强函数
    @AfterThrowing(value = "execution(* cn.service.ServiceImple.MainMethod(..))")
    public void AfterThrowingMethod(){
        System.out.println("作为异常增强处理");
    }


    //    最终增强:无论怎样都会执行的
    @After(value = "execution(* cn.service.ServiceImple.MainMethod(..))")
    public void AfterMethod(){
        System.out.println("作为最终增强处理");
    }
}

实现类展示

实现类会根据输入的结果,是否存在异常来进行之后操作

public class SpringIOCTest {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("SpringTest.xml");
        ServiceImple serviceimple = context.getBean("serviceimple", ServiceImple.class);

//        直接调用主函数。在不修改代码的情况下进行了添加新的功能
        serviceimple.MainMethod(1);
    }
}

在这里插入图片描述

在这里插入图片描述

相同切入点抽取

通过上面代码我们发现多个切入点之间存在相同,为了避免代码的重复

  //相同切入点抽取
    @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void pointdemo() {
    }

    //前置通知
//@Before 注解表示作为前置通知
    @Before(value = "pointdemo()")
    public void before() {
        System.out.println("before.........");
    }

有多个增强类多同一个方法进行增强,设置增强类优先级

//  (1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高

@Component
@Aspect
@Order(1)
public class PersonProxy{
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值