首页 > 其他分享 >46.Spring(AOP)学习整理

46.Spring(AOP)学习整理

时间:2024-05-20 10:18:35浏览次数:29  
标签:连接点 46 Spring void 通知 AOP println public

Spring AOP 面向切面编程

它依旧是一种设计思想 本质还是为了松散耦合

先去分一个概念

  1. OOP面向对象编程
    实体及其属性行为
  2. AOP面向切面编程
    某个阶段或者步骤

看下图解:

image

image

代码业务的实现都是纵向 而AOP切面实现为横向

AOP的一些术语:

连接点(Jointpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点,在AOP中表示为在哪里干;
切入点(Pointcut): 选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法,在AOP中表示为在哪里干的集合;
通知(Advice):在连接点上执行的行为,通知提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知;在AOP中表示为干什么;
方面/切面(Aspect):横切关注点的模块化,比如上边提到的日志组件。可以认为是通知、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;在AOP中表示为在哪干和干什么集合;
引入(inter-type declaration):也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象), 在AOP中表示为干什么(引入什么);
目标对象(Target Object):需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为被通知对象;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,在AOP中表示为对谁干;
织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。在AOP中表示为怎么实现的;
AOP代理(AOP Proxy):AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。在AOP中表示为怎么实现的一种典型方式;


通知类型:

通知类型:前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
异常通知(After throwing advice):在方法抛出异常退出时执行的通知。最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。


我们看一个例子:

先引入依赖:
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.20.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
AspectJ是什么呀

AspectJ是一个java实现的AOP框架,它能够对java代码进行AOP编译(一般在编译期进行),让java代码具有AspectJ的AOP功能(当然需要特殊的编译器)

关于AOP的配置方式 和 AspectJ动态静态织入 直接看例子:


业务:
public interface UserService {
    public void add();
    public void delete();
    public void select();
    public void update();
}
public class UserServiceImpl implements UserService {
    public void add(){
        System.out.println("增加");
    }
    public void delete(){
        System.out.println("删除");
    }
    public void select(){
        System.out.println("查询");
    }
    public void update(){
        System.out.println("新增");
    }
}

package log;

import org.springframework.aop.AfterReturningAdvice;
//接口使用JDK代理
import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法 返回结果为:"+returnValue);
    }
}

package log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class BeforeLog implements MethodBeforeAdvice {

    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"执行了");
    }
}
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.xsd">

    <bean id="userService" class="Service.UserServiceImpl"/>
    <bean id="BeforeLog" class="log.BeforeLog"/>
    <bean id="AfterLog" class="log.AfterLog"/>

    <aop:config>
<!--        切入点-->
<!--        *(方法修饰符):这表示匹配任何方法修饰符,如public、private、protected等。-->
<!--        Service.UserServiceImpl(返回类型和方法名):这里实际上看起来像是包和类的组合,但在Java中这不是有效的全限定类名。通常,你会看到类似com.example.service.UserServiceImpl这样的全限定类名。-->
<!--        *(方法名):这表示匹配任何方法名。-->
<!--        (..)(参数列表):两个点(..)表示匹配任何数量和类型的参数-->
        <aop:pointcut id="pointcut" expression="execution(* Service.UserServiceImpl.*(..))"/>
<!--        环绕执行-->
        <aop:advisor advice-ref="BeforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

测试:
        //第一种方式 实现spring API接口
        ApplicationContext context = new ClassPathXmlApplicationContext("applicitionContext.xml");
         //动态代理的为接口 即UserService
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
        System.out.println("================================");

自定义类实现
public class DiyAOP {
    public void before(){
        System.out.println("方法前");
    }
    public void after(){
        System.out.println("方法后");
    }
}
<?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.xsd">
    <bean id="userService" class="Service.UserServiceImpl"/>
    <bean id="diy" class="diy.DiyAOP"/>
    <aop:config>
<!--        切面-->
        <aop:aspect ref="diy">
            <aop:pointcut id="pointcut" expression="execution(* Service.UserServiceImpl.*(..))"/>
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

</beans>
测试:
        //第二种方式 自定义类
        ApplicationContext context2 = new ClassPathXmlApplicationContext("applicationContextDiy.xml");
        UserService userService2 = context2.getBean("userService", UserService.class);
        userService2.add();
        System.out.println("================================");

注解配置

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class DiyAnnotaion {
    @Before("execution(* Service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("方法前");
    }

    @After("execution(* Service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("方法后");
    }
}
<?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.xsd">
    <bean id="userService" class="Service.UserServiceImpl"/>
    <bean id="diyAnnotation" class="diy.DiyAnnotaion"/>
<!--    开启注解支持-->
    <aop:aspectj-autoproxy/>
</beans>


        //第三种方式 注解
        ApplicationContext context3 = new ClassPathXmlApplicationContext("applicationContextDiyAnnotion.xml");
        UserService userService3 = context3.getBean("userService", UserService.class);
        userService3.add();

效果如图:

image

关于一些spring 中xml的约束声明 参考:https://blog.csdn.net/qq_43418737/article/details/122666966
文章更深入详细 参考:
https://pdai.tech/md/spring/spring-x-framework-aop.html

标签:连接点,46,Spring,void,通知,AOP,println,public
From: https://www.cnblogs.com/gaodiyuanjin/p/18201308

相关文章

  • 基于 Spring Boot3、Vue3!这套小说系统开源了...
    大家好,我是Java陈序员。今天,给大家介绍一个基于SpringBoot3、Vue3前后端分离的小说项目,集成了主流的技术栈,可供学习使用!关注微信公众号:【Java陈序员】,获取开源项目分享、AI副业分享、超200本经典计算机电子书籍等。项目介绍novel——一套基于SpringBoot3+Vue3开发......
  • Spring 对于事务上的应用的详细说明
    1.Spring对于事务上的应用的详细说明@目录1.Spring对于事务上的应用的详细说明每博一文案2.事务概述3.引入事务场景3.1第一步:准备数据库表3.2第二步:创建包结构3.3第三步:准备对应数据库映射的Bean类3.4第四步:编写持久层3.5第五步:编写业务层3.6第六步:编写Spring配置......
  • Spring IoC注解式开发无敌详细(细节丰富)
    1.SpringIoC注解式开发无敌详细(细节丰富)@目录1.SpringIoC注解式开发无敌详细(细节丰富)每博一文案2.注解回顾3.Spring声明Bean的注解3.1Spring注解的使用3.1.1特别的:如果要扫描的是多个包3.1.2Spring选择性实例化Bean对象3.2通过注解实现“Spring的注入”3.2.1@Value......
  • SpringCloud(3)-OpenFeign相关配置
    OpenFeign是个声明式WebService客户端,使用OpenFeign让编写WebService客户端更简单。SpringCloud对OpenFeign进行了封装使其支持了SpringMVC标准注解和HttpMessageConverters。OpenFeign可以与Eureka和Ribbon组合使用以支持负载均衡。1.配......
  • 10046 event
    转自:https://www.cnblogs.com/dbabd/p/10319479.html#autoid-3-0-01.前言作为SQLTrace的扩展功能,Oracle10046event(10046事件)是一个重要的调试事件,也可以说是系统性能分析时最重要的一个事件,它包含比SQLTrace更多的信息。但可惜的是,10046事件并不是Oracle官方提供给用户的......
  • SpringCloud(2)-Ribbon相关配置
    Ribbon是一套提供客户端负载均衡的工具Ribbon=负载均衡+RestTemplateRibbon属于进程内LoadBalance,含义是将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些服务地址可用,然后再从这些地址中选择出一个合适的服务地址。Ribbon常见负载算法:我们接下来以随机负载......
  • SpringCloud(1)-Eureka相关配置
    1.新建Module-注册中心作为注册中心1.1配置pom.xml<!--引入eureka-server--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId&g......
  • spring事务原理
    1、事务概念事务,就是一组操作数据库的动作集合,要么全部成功,要么全部失败。spring支持两种方式的事务:编程式事务:编程式事务管理使用TransactionTemplate,需要显式执行事务,比如,需要显示调用commit或者rollback方法。声明式事务:声明式事务管理建立在AOP之上的。其本质是......
  • Spring 面向切面编程AOP 详细讲解
    1.Spring面向切面编程AOP详细讲解@目录1.Spring面向切面编程AOP详细讲解每博一文案2.AOP介绍说明2.1AOP的七大术语2.2AOP当中的切点表达式3.使用Spring对AOP的实现使用3.1准备工作3.2Spring基于AspectJ的AOP注解式开发3.2.1实现步骤3.2.2各个通知类型的说明3......
  • 挑战程序设计竞赛 2.1章习题 poj 3046 Ant Counting
    https://vjudge.net.cn/problem/POJ-3046#author=GPT_zh有一天,贝西在蚂蚁山里探头探脑,看着蚂蚁们来来回回地觅食。她发现很多蚂蚁都是兄弟姐妹,彼此无法区分。她还发现,有时只有一只蚂蚁去觅食,有时几只,有时全部。这就产生了大量不同组合的蚂蚁!有点数学天赋的贝茜开始琢磨起来......