SpringAOP

2023-09-17 22:51:27

AOP实现原理

Spring AOP 基于动态代理实现原理:
  ○ 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
  ○ 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);

AOP有关知识点(通知+aspect+pointcut)

AOP通知类型:
AOP将抽取出来的共性功能称为通知;通知类型:以通知在上下文中的具体位置作为划分
  前置通知(Before)
  后置通知(After)
  返回通知(After-returning)
  异常通知(After-throwing)
  环绕通知(Around)

AOP重要的知识点。

AOP切面:切点+通知

SpringAOP+AspectJ实现步骤:
1.坐标
2.配置

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.28</version>
        </dependency>


        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>


    </dependencies>

AspectJ 切面:可以理解为要注入方法的所有通知

切点:到哪一个类的哪一个方法

AOP实现流程

1,正常的制作程序

 以上一篇的转账来说,事务管理注入到service的每一个方法当中。
2,将非共性功能开发到对应的目标对象类中,并制作成切入点方法,绿色的都可以当切入点

  @Override
    public void save(String name) {

        System.out.println("===>业务新增");
        int a = 10/0;//模拟异常
    }

    @Override
    public int delete(int num) {
        System.out.println("===>业务删除");
        return 0;
    }

    @Override
    public void findAll() {
        System.out.println("===>业务查询");
    }

3,将共性功能独立开发出来,制作成“通知”

事务的开启到AOP前置通知的地方

事务的提交可以放到AOP的返回通知的地方。

事务失败可以放到AOP的异常通知的地方。

事务关闭可以放到AOP的后置通知的地方。finally必须要执行的那个模块。

package com.apesource.util;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Date;

/**
 * @author 
 * @version 1.0
 * @since 2023/8/4
 */
public class LoggerUtil {
    //前置通知
    public void beforeMethod(){
        System.out.println("前置通知=====>"+new Date());
    }
    //返回通知
    public void afterRrturnMethod(){
        System.out.println("返回通知=====>"+new Date());
    }
    //异常通知
    public void throwMethod(){
        System.out.println("异常通知=====>"+new Date());
    }
    //后置通知
    public void afterMethod(){
        System.out.println("后置通知=====>"+new Date());
    }

    //环绕通知
    public Object arroundMethod(ProceedingJoinPoint pjp){
        Object obj = null;

        try {
            //环绕通知---前置通知
            System.out.println("环绕通知---前置通知");
            Object[] objs = pjp.getArgs();
            obj = pjp.proceed(objs);
            //环绕通知---返回通知
            System.out.println("环绕通知---返回通知");
        } catch (Throwable throwable) {
            //环绕通知---异常通知
            System.out.println("环绕通知---异常通知");
            throwable.printStackTrace();
        } finally {
            //环绕通知---后置通知
            System.out.println("环绕通知---后置通知");
        }

        return obj;

    }


}

4.在配置文件中,声明“切入点”,该步骤可以让Spring定位到实体类的方法

切点表达式配置语法:
execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
eg:
    execution(public void com.apesource.service.ServiceImp.findAll())
1.修饰符可以省略代表任意
    execution(返回值 包名称.类名称.方法名称(参数列表))
2.返回值可以使用“*”代表任意
    execution(* 包名称.类名称.方法名称(参数列表))
3.包名可以使用“*”代表任意名称
    execution(* *.*.*.类名称.方法名称(参数列表))
4.包名可以使用“..”代表任意个数
    execution(* *...类名称.方法名称(参数列表))
5.类名与方法名可以使用“*”代表任意
    execution(* *...*.*(参数列表))
6.参数列表可以使用".."代表任意个数任意类型
    execution(* *...*.*(..))
    如果有参数
        int======>int
        String===>java.lang.String

@Pointcut(value = "execution(* com.apesource.service.*.*(..))")
    public  void dian(){
    }

修饰符为任意,返回值任意, com.apesource.service下的所有类的所有方法。

5.在配置文件中,声明"切入点"与"通知"间的关系(含通知类型),即"切面"

@Component
@Aspect
public class LoggerUtil {


    @Pointcut(value = "execution(* com.apesource.service.*.*(..))")
    public  void dian(){
    }
    //前置通知
    @Before("dian()")
    public void beforeMethod(){
        System.out.println("前置通知=====>"+new Date());
    }
    //返回通知
    @AfterReturning("dian()")
    public void afterRrturnMethod(){
        System.out.println("返回通知=====>"+new Date());
    }
    //异常通知
    @AfterThrowing("dian()")
    public void throwMethod(){
        System.out.println("异常通知=====>"+new Date());
    }
    //后置通知
    @After("dian()")
    public void afterMethod(){
        System.out.println("后置通知=====>"+new Date());
    }

    //环绕通知
    @Around("dian()")
    public Object arroundMethod(ProceedingJoinPoint pjp){

        Object obj = null;

        try {
            //环绕通知---前置通知
            System.out.println("环绕通知---前置通知");
            Object[] objs = pjp.getArgs();
            obj = pjp.proceed(objs);//proceed等于invoke方法
            //环绕通知---返回通知
            System.out.println("环绕通知---返回通知");
        } catch (Throwable throwable) {
            //环绕通知---异常通知
            System.out.println("环绕通知---异常通知");
            throwable.printStackTrace();
        } finally {
            //环绕通知---后置通知
            System.out.println("环绕通知---后置通知");
        }

        return obj;

    }

●运行阶段(AOP完成)=============spring帮我们做的
    ◆Spring容器加载配置文件,监控所有配置的“切入点”方法的执行
    ◆当监控到“切入点”方法被运行,使用“代理”机制,动态创建“目标对象”的“代理对象”,
 根据“通知类别”,在“代理对象”的对应位置将“通知”对应的功能“织入”,完成完整的代码逻辑并运行 

    <context:component-scan base-package="com.apesource"></context:component-scan>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>


   <!--开启aop配置xml版本-->
<!--    <aop:config>-->
<!--        <aop:aspect id="mian" ref="loggerUtil">-->
<!--            <aop:pointcut id="dian" expression="execution(* com.apesource.service.*.*(..))"/>-->
 <!--      <aop:before method="beforeMethod" pointcut-ref="dian"></aop:before>
 <!--           <aop:after-returning method="afterRrturnMethod" pointcut-ref="dian"></aop:after-returning>
 <!--        <aop:after-throwing method="throwMethod" pointcut-ref="dian"></aop:after-throwing>-->
<!--        <aop:after method="afterMethod" pointcut-ref="dian"></aop:after>&ndash;&gt;-->
<!--     <aop:around method="arroundMethod" pointcut-ref="dian"></aop:around>-->
<!--        </aop:aspect>-->
<!--    </aop:config>-->

 <!--开启aop配置注解版-->


    <context:component-scan base-package="com.apesource"></context:component-scan>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 test测试类。

package com.apesource.test;

import com.apesource.service.IService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 
 * @version 1.0
 * @since 2023/8/4
 */
public class Test01 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        IService service = (IService) applicationContext.getBean("serviceImp");
        service.save("今天周五");
//        service.delete(5);
//        service.findAll();

    }
}

更多推荐

百度测开面试题分享

1、java常用的异常处理机制?Java常用的异常处理机制有以下几种:1)try-catch-finally语句:用于捕获和处理异常。将可能抛出异常的代码放在try块中,然后在catch块中处理异常。无论是否发生异常,finally块中的代码都会被执行。try{//可能抛出异常的代码}catch(ExceptionTy

Java面试题之——异常和错误

提示:解释Java中的异常和错误是什么,以及它们之间的区别是什么?文章目录前言从定义上来说:从处理方式来看:总结⭐️好书推荐前言提示:这里可以添加本文要记录的大概内容:在Java编程语言中,异常和错误都是程序运行时可能出现的问题,但它们之间存在一些重要的区别。提示:以下是本篇文章正文内容,下面案例可供参考从定义上来说:

Linux内核:解密操作系统的核心技术

大家好,我是运维家的作者,今天我要和大家聊一聊Linux内核。作为操作系统的核心技术,Linux内核扮演着至关重要的角色。它像是一个大总管,掌控着整个操作系统的各种资源和功能。什么是Linux内核?就像我们人类身体的大脑一样,Linux内核是Linux操作系统的核心组件。它运行在系统的最底层,负责管理和分配计算机的硬件

社交媒体商业禁令冲击:TikTok如何应对印尼政策变化?

随着社交媒体的普及和发展,各国政府开始越来越关注这一领域的监管和控制。印尼政府最近的决定,禁止在社交媒体上进行商品交易,引起了广泛的关注。这一政策变化对TikTok等社交媒体平台带来了巨大的挑战,要求它们重新审视商业模式并采取应对措施。政策背景近年来,印尼的进口条件不断收紧,免税门槛逐渐下调,甚至发布了新的进口规则,限

Python Q-learning 算法 --2023博客之星候选--城市赛道

Q-learning是一种强化学习算法,用于解决马尔可夫决策过程(MDP)问题。什么是马尔可夫决策过程(MDP)问题?马尔可夫决策过程(MDP)是一种用于建模序贯决策问题的数学框架。在MDP中,决策问题被建模为一个基于马尔可夫链的数学模型。MDP由以下要素组成:状态空间(StateSpace):一组可能的状态,用来描述

微服务如何改变软件开发:实战经验与最佳实践分享

文章目录什么是微服务?微服务实战经验1.定义明确的服务边界2.使用API网关3.自动化部署和持续集成4.监控和日志记录微服务最佳实践1.文档和通信2.弹性设计3.安全性4.版本控制5.监控和警报微服务的未来🎉欢迎来到架构设计专栏~微服务如何改变软件开发:实战经验与最佳实践分享☆*o(≧▽≦)o*☆嗨~我是IT·陈寒�

中秋特辑——3D动态礼盒贺卡(可监听鼠标移动)

前言「作者主页」:雪碧有白泡泡「个人网站」:雪碧的个人网站「推荐专栏」:★java一站式服务★★React从入门到精通★★前端炫酷代码分享★★从0到英雄,vue成神之路★★uniapp-从构建到提升★★从0到英雄,vue成神之路★★解决算法,一个专栏就够了★★架构咱们从0说★★数据流通的精妙之道★★后端进阶之路★文章目

MySQL数据库下的Explain命令深度解析

Explain是一个非常有的命令,可以用来获取关于查询执行计划的信息,以及如何解释输出。Explain命令是查看查询优化器如何决定执行查询的主要方法。这个功能有一定的局限性,并不总是会说出真相,但是它的输出是可以获取的最好信息,值得花时间了解,可以学习到查询是如何执行的。01调用Explain要使用Explain,只需

消息队列的模拟实现(二)

消息队列的创建消息队列代码部分-(1)一、构思项目的组成创建项目后添加依赖建立交换机表、队列表和绑定表ExchangeQueueBindingMessage实现信息属性类在`Sqlite`中建表SQL建表语句实现接口调用建表操作`Map`数据结构的序列化创建数据库和连接数据库添加数据添加接口方法操作数据库在`MateM

java内嵌浏览器CEF-JAVA、jcef、java chrome

java内嵌浏览器CEF-JAVA、jcef、javachromejcef是老牌cef的chrome内嵌方案,可以进行java-chrome-h5-桌面开发,下面为最新版本(2023年9月22日10:33:07)JCEF(JavaChromiumEmbeddedFramework)是一个基于GoogleChromium

如何通过AI视频智能分析技术,构建着装规范检测/工装穿戴检测系统?

众所周知,规范着装在很多场景中起着重要的作用。违规着装极易增加安全隐患,并且引发安全事故和质量问题,例如,在化工工厂中,倘若员工没有穿戴符合要求的特殊防护服和安全鞋,将有极大可能受到有害物质的侵害,对身体健康和生命安全带来严重的威胁。TSINGSEE青犀视频AI算法平台的着装规范检测/工装穿戴检测算法,是基于AI深度学

热文推荐