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的案例实践,我们通过赤兔马 、侦察兵来测试;学了两个前置通知和正常返回通知;


目录
相关文章
|
1月前
|
XML 安全 Java
|
2月前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
79 0
|
20天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
6天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
36 8
|
15天前
|
Java 开发者 Spring
理解和解决Spring框架中的事务自调用问题
事务自调用问题是由于 Spring AOP 代理机制引起的,当方法在同一个类内部自调用时,事务注解将失效。通过使用代理对象调用、将事务逻辑分离到不同类中或使用 AspectJ 模式,可以有效解决这一问题。理解和解决这一问题,对于保证 Spring 应用中的事务管理正确性至关重要。掌握这些技巧,可以提高开发效率和代码的健壮性。
45 13
|
27天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
48 5
|
1月前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
68 8
|
2月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
84 5
|
4月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
91 1
|
2月前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
251 1
什么是AOP面向切面编程?怎么简单理解?