JAVAEE框架之Spring AOP

简介: JAVAEE框架之Spring AOP

JAVAEE框架之Spring

六.AOP

AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。

当我们系统已经设计好了之后,要去增加功能的时候,尽量少的去之前的代码。

JAVA:面向接口编程,可以定义若干接口,使用实现类实现后续需要增加的功能。

从该图可以很形象地看出,所谓切面,相当于应用对象间的横切点,我们可以将其单独抽象为单独的模块。

再举一个案例:

现实生活的案例,之前的老的居民楼,家里都有水表、电表,每到月末的时候,都有水利公司、电力公司的员工去抄表,电力公司的员工,挨家挨户的去抄表,有问题:太累、可能用户不在家,需要再次上门。这时候电力公司,就想到了AOP,面向切面编程,把各个各户的电表统一放到一个电表箱,由电力公司员工(宋光明)来抄表,大家看下,这时候,抄表员的效率是不是就大幅度提高了。

6.1 为什么需要 AOP

想象下面的场景,开发中在多个模块间有某段重复的代码,我们通常是怎么处理的?显然,没有人会靠“复制粘贴”吧。在传统的面向过程编程中,我们也会将这段代码,抽象成一个方法,然后在需要的地方分别调用这个方法,这样当这段代码需要修改时,我们只需要改变这个方法就可以了。然而需求总是变化的,有一天,新增了一个需求,需要再多出做修改,我们需要再抽象出一个方法–》接口,然后再在需要的地方分别调用这个方法–>接口的实现类,又或者我们不需要这个方法了,我们还是得删除掉每一处调用该方法的地方。实际上涉及到多个地方具有相同的修改的问题我们都可以通过 AOP 来解决。

使用场景:

Authentication 权限
 Caching 缓存
 Context passing 内容传递
 Error handling 错误处理
 Lazy loading 懒加载
 Debugging  调试
 logging, tracing, profiling and monitoring 记录跟踪 优化 校准
 Performance optimization 性能优化
 Persistence  持久化
 Resource pooling 资源池
 Synchronization 同步
 Transactions 事务

6.2 术语

  • 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
  • 连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用
  • 切点(PointCut): 可以插入增强处理的连接点。
  • 切面(Aspect): 切面是通知和切点的结合,相同功能模块联系起来构成切面。
  • 引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
  • 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。建立业务类和功能的关联,就是织入,类似于织布。

6.3 jar包依赖

pom.xml文件

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
    </dependency>

6.4 使用AOP的几种方式

  • XML方式
  • 注解方式
    AOP通知类型
    前置通知Before advice:在连接点(方法)前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。
    正常返回通知After returning advice:在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。
    异常返回通知After throwing advice:在连接点抛出异常后执行。
    后置通知After (finally) advice:在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。
    环绕通知Around advice:环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。

  • 围绕之前给大家布置的关羽骑马的案例来讲:
    骑马:赤兔马;接口–》坐骑
    关羽和魏国交战,魏国要针对蜀国关二爷进行侦查,侦查的时候,放一个侦察兵过来;
    侦察兵只要发现赤兔马起来,就给个通知。有几个通知,有提前通知,有滞后通知有其他通知等。
    侦察兵做的是提前通知,预警工作;

6.4.1 接口类

public interface Zuoqi {
    public void eat(int weight);
    public void  run(int juli) throws Exception;//跑
}

6.4.2 目标对象

public class Horse implements Zuoqi {
    private String city="郑州";
    public void eat(int weight) {
        System.out.println("赤兔马在吃草..."+weight+"斤");
    }
    //方法的重载
    public void run(int juli) throws Exception {
        if(city.equals("麦城"))
            throw new Exception("赤兔马被绊倒了...");
        System.out.println("赤兔马跑起来了....");
    }
}

6.4.3 切面类

package com.aaa.pojo;
import org.aspectj.lang.JoinPoint;
/**
 * Created by 张晨光 on 2020/6/22 15:18
 * 侦察兵类:可以针对坐骑进行侦查操作;
 */
public class ZcbAspect {
    //前置通知,提前通知魏国人跑;只要马一跑就通知,太累人了。设置一个距离;
    //又讲了一个JoinPoint:连接点类;它有目标对象相关方法调用的参数;
    public void qian(JoinPoint jp){
        //这时候就要获取刚才的方法参数;
        Object[] args=jp.getArgs();  //获取连接点类的参数,即目标对象切入点方法的参数,有几个;
        //测试一下:输出方法名;
        String name = jp.getSignature().getName();
        System.out.println("测试目标对象方法名:"+name);
        Integer juli= (Integer) args[0]; //将Object类型转换为Integer类型;
        if(name.equals("run"))
        {
            if(juli<=50)
                System.out.println("快跑,赤兔马快来了...");
        }
        if(name.equals("eat")){
            System.out.println("不用管它..");
        }
    }
    //正常返回通知
    public void hou(){
        System.out.println("赤兔马拉了一堆马粪走了...");
    }
    //异常通知;
    public void excep(JoinPoint jp,Exception e){
        System.out.println("方法执行异常:"+e.getMessage());
    }
    //5.环绕通知:返回类型是Object不同;参数不同; 测试环绕通知的时间;
    //可以方法前后
    public Object around(ProceedingJoinPoint pjp)throws Throwable{
        String method=pjp.getSignature().getName();//获取方法签名;
        long begin=System.currentTimeMillis();//获取开始时间的毫秒数;
        System.out.println("开始计时:");
        try {
            return pjp.proceed();
        } finally {
            long end=System.currentTimeMillis();//获取的结束的时间;
            System.out.println("侦察兵侦查时间:"+(end-begin));
        }
    }
}

6.4.4 xml配置

<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<!--使用xml的方式,来实现aop的功能理解-->
<!--1.目标对象:赤兔马-->
<bean id="chitu" class="com.aaa.pojo.Horse"/>
<!--2.切面类:此处是侦察兵类;-->
<bean id="zcb" class="com.aaa.pojo.ZcbAspect"/>
<!--3.Aop配置,工作就是织布,就是织入;将切面类和目标对象建立关联
   这是一个重点,理解即可,不用背,不用记代码-->
<aop:config>
    <!--3.1 切入点:id名;expression:execution(方法名)表达式;切入点,切的赤兔马(目标对象),run()-->
    <aop:pointcut id="p1" expression="execution(void *(int))"/>
    <!--3.2 切面类:ref 引入之前定义好的侦察兵-->
    <aop:aspect ref="zcb">
        <!--3.2.1侦察兵,开始前置通知,给魏王报信-->
        <aop:before method="qian" pointcut-ref="p1"/>
        <aop:after-returning method="hou" pointcut-ref="p1"/>
        <!--注意异常通知的参数有三个;-->
        <aop:after-throwing method="excep" pointcut-ref="p1" throwing="e"/>
    </aop:aspect>
     <!--最终通知-->
        <aop:after method="last" pointcut-ref="p1"/>
        <!--环绕通知-->
        <aop:around method="around" pointcut-ref="p1"/>
</aop:config>
</beans>

6.4.5 测试类

public class TestAop01 {
    @Test
    public void test() throws Exception {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        Zuoqi zuoqi= (Zuoqi) ac.getBean("chitu");
        //zuoqi.eat(5); //吃了5斤草
        zuoqi.run(30);
    }
}

总结:

1.aop的概念;现实案例和开发案例的理解;

2.aop的术语,理解,不用记忆;

ingframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">

```

6.4.5 测试类

public class TestAop01 {
    @Test
    public void test() throws Exception {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        Zuoqi zuoqi= (Zuoqi) ac.getBean("chitu");
        //zuoqi.eat(5); //吃了5斤草
        zuoqi.run(30);
    }
}

总结:

1.aop的概念;现实案例和开发案例的理解;

2.aop的术语,理解,不用记忆;

3.aop的案例实践,我们通过赤兔马 、侦察兵来测试;学了两个前置通知和正常返回通知;


目录
相关文章
|
12天前
|
XML 安全 Java
|
15天前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
21 0
|
8天前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
40 8
|
14天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
41 5
|
18天前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
32 6
|
18天前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
18天前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
32 5
|
XML Java 数据格式
JavaEE Spring IoC注解
1. @Resource--手动注入 使用Field注入(用于注解方式),注入依赖对象可以采用手工装配或自动装配.在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。
781 0
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
201 2
|
19天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
38 1
SpringBoot入门(7)- 配置热部署devtools工具