SpringAOP入门案例

news2024/12/23 12:24:38

在这里插入图片描述

package com.elf.spring.aop.aspectj;
/**
 * @author 45
 * @version 1.0
 */
public interface UsbInterface {
    public void work();
}

package com.elf.spring.aop.aspectj;
import org.springframework.stereotype.Component;
/**
 * @author 45
 * @version 1.0
 */
@Component //把Phone对象当做一个组件注入容器
public class Phone implements UsbInterface{
    @Override
    public void work() {
        System.out.println("手机开始工作了....");
    }
}

package com.elf.spring.aop.aspectj;
import org.springframework.stereotype.Component;
/**
 * @author 45
 * @version 1.0
 */
@Component //将Camera注入到spring容器
public class Camera implements UsbInterface {
    @Override
    public void work() {
        System.out.println("相机开始工作...");
    }
}
package com.elf.spring.aop.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author 45
 * @version 1.0
 * 切面类 , 类似于我们以前自己写的MyProxyProvider,但是功能强大很多
 *
 */
@Order(value = 2)//表示该切面类执行的顺序, value的值越小, 优先级越高
@Aspect //表示是一个切面类[底层切面编程的支撑(动态代理+反射+动态绑定...)]
@Component //会注入SmartAnimalAspect到容器
public class SmartAnimalAspect {


    //定义一个切入点, 在后面使用时可以直接引用, 提高了复用性
    @Pointcut(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float)))")
    public void myPointCut() {
    }

    //希望将f1方法切入到SmartDog-getSum前执行-前置通知

    /**
     * 解读
     * 1. @Before 表示前置通知:即在我们的目标对象执行方法前执行
     * 2. value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float)
     * 指定切入到哪个类的哪个方法  形式是: 访问修饰符 返回类型 全类名.方法名(形参列表),
     *     带形参列表是因为方法名可能相同,参数个数不同构成重载,以便区分.
     * 3. showBeginLog方法可以理解成就是一个切入方法, 这个方法名是可以程序员指定  比如:showBeginLog
     * 4. JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象
     * , 通过该方法,程序员可以获取到 相关信息
     *
     * @param joinPoint
     */
    //@Before(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))")
    //这里我们使用定义好的切入点
    @Before(value = "myPointCut()")
    //如果说是一个切入方法,那么形参是JoinPoint joinPoint,用aop来做的开发主要是由aspectj框架来支撑的
    public void showBeginLog(JoinPoint joinPoint) {
        //通过连接点对象joinPoint 可以获取方法签名
        Signature signature = joinPoint.getSignature();
        //signature.getName()方法签名指的是:com.elf.spring.aop.aspectj.SmartDog.getSum
        System.out.println("SmartAnimalAspect-切面类showBeginLog()[使用的myPointCut()]-方法执行前-日志-方法名-" + signature.getName() + "-参数 "
                + Arrays.asList(joinPoint.getArgs()));//(float, float)
    }

    //返回通知:即把showSuccessEndLog方法切入到目标对象方法正常执行完毕后的地方
    //老韩解读
    //1. 如果我们希望把目标方法执行的结果,返回给切入方法
    //2. 可以再 @AfterReturning 增加属性 , 比如 returning = "res"
    //3. 同时在切入方法增加 Object res
    //4. 注意: returning = "res" 和 Object res 的 res名字一致
    //@AfterReturning(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))", returning = "res")
    //使用切入点
    @AfterReturning(value = "myPointCut()", returning = "res")
    public void showSuccessEndLog(JoinPoint joinPoint, Object res) {
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);
    }


    //异常通知:即把showExceptionLog方法切入到目标对象方法执行发生异常的的catch{}
    //@AfterThrowing(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))", throwing = "throwable")
    //直接使用切入点表达式
    @AfterThrowing(value = "myPointCut()", throwing = "throwable")
    public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);
    }

    //最终通知:即把showFinallyEndLog方法切入到目标方法执行后(不管是否发生异常,都要执行 finally{})
    //@After(value = "execution(public float com.elf.spring.aop.aspectj.SmartDog.getSum(float, float))")
    //直接使用切入点
    @After(value = "myPointCut()")
    public void showFinallyEndLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名-" + signature.getName());
    }

    //新的前置通知
    //@Before(value = "execution(public void com.elf.spring.aop.aspectj.Phone.work()) || execution(public void com.elf.spring.aop.aspectj.Camera.work())")
    //public void hi(JoinPoint joinPoint) {
    //    Signature signature = joinPoint.getSignature();
    //    System.out.println("切面类的hi()-执行的目标方法-" + signature.getName());
    //}

    //切入表达式也可以指向接口的方法, 这时切入表达式会对实现了接口的类/对象生效
    //比如下面我们是对UsbInterface 切入,那么对实现类Phone 和 Camera对象都作用了
    @Before(value = "execution(public void com.elf.spring.aop.aspectj.UsbInterface.work())")
    public void hi(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的hi()-执行的目标方法-" + signature.getName());
    }


    //给Car配置一个前置通知,即将ok1()方法切入到Car类的run()方法前
    @Before(value = "execution(public void Car.run())")
    public void ok1(JoinPoint joinPoint) {

        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的ok1()-执行的目标方法-" + signature.getName());

    }

    //返回通知
    @AfterReturning(value = "execution(public void Car.run())")
    public void ok2(JoinPoint joinPoint) {

        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的ok2()-执行的目标方法-" + signature.getName());

    }

    //异常通知
    @AfterThrowing(value = "execution(public void Car.run())")
    public void ok3(JoinPoint joinPoint) {

        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的ok3()-执行的目标方法-" + signature.getName());

    }

    //后置通知
    @After(value = "execution(public void Car.run())")
    public void ok4(JoinPoint joinPoint) {


        Signature signature = joinPoint.getSignature();
        System.out.println("切面类的ok4()-执行的目标方法-" + signature.getName());
        //演示一下JoinPoint常用的方法.
        joinPoint.getSignature().getName(); // 获取目标方法名
        joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的简单类名
        joinPoint.getSignature().getDeclaringTypeName(); // 获取目标方法所属类的类名
        joinPoint.getSignature().getModifiers(); // 获取目标方法声明类型(public、private、protected)
        Object[] args = joinPoint.getArgs(); // 获取传入目标方法的参数,返回一个数组
        joinPoint.getTarget(); // 获取被代理的对象
        joinPoint.getThis(); // 获取代理对象自己
    }
}

package com.elf.spring.aop.aspectj;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 45
 * @version 1.0
 */
public class AopAspectjTest {

    @Test
    public void smartDogTestByProxy() {

        //得到spring容器
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans08.xml");
        //这里我们需要通过接口类型来获取到注入的SmartDog对象-就是代理对象
        SmartAnimalable smartAnimalable =
                ioc.getBean(SmartAnimalable.class);

        //SmartAnimalable smartAnimalable =
        //        (SmartAnimalable)ioc.getBean("smartDog");

        smartAnimalable.getSum(10, 2);

        System.out.println("smartAnimalable运行类型="
                + smartAnimalable.getClass());

        System.out.println("=============================");

        //smartAnimalable.getSub(100, 20);

    }

    @Test
    public void smartDogTestByProxy2() {

        //得到spring容器
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans08.xml");

        UsbInterface phone = (UsbInterface) ioc.getBean("phone");
        UsbInterface camera = (UsbInterface) ioc.getBean("camera");

        phone.work();

        System.out.println("==================");

        camera.work();

    }

    @Test
    public void test3() {
        //得到spring容器
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans08.xml");

        Car car = ioc.getBean(Car.class);

        //说明: car对象仍然是代理对象
        System.out.println("car的运行类型=" + car.getClass());

        car.run();

    }

    @Test
    public void testDoAround() {
        //得到spring容器
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans08.xml");


        SmartAnimalable smartAnimalable =
                ioc.getBean(SmartAnimalable.class);

        smartAnimalable.getSum(10, 2);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1039238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何快速提高沃尔玛、亚马逊产品的权重和销量,自养号测评的重要性!

据沃尔玛最新财报显示,其第二季度营业收入达到1616亿美元,同比增长5.74%;第二季度净利润约为79亿美元,同比增长53%。其中,沃尔玛在美国电商业务销售额同比增长24%。 其用户忠诚度也很较高,沃尔玛每月独立访…

Linux - Python安装

准备 openssl下载 python3下载 openssl安装目录:/usr/local/openssl python安装目录:/usr/local/python 将下载的文件上传至上面目录 部署 openssl安装 cd /usr/local/openssl tar -zxvf openssl-1.1.1w.tar.gz cd openssl-1.1.1w ./config --pref…

公网远程访问GeoServe Web管理界面【内网穿透】

文章目录 前言1.安装GeoServer2. windows 安装 cpolar3. 创建公网访问地址4. 公网访问Geo Servcer服务5. 固定公网HTTP地址 前言 GeoServer是OGC Web服务器规范的J2EE实现,利用GeoServer可以方便地发布地图数据,允许用户对要素数据进行更新、删除、插入…

蓝桥杯备赛-上学迟到

上学迟到 P5707 【深基2.例12】上学迟到 - 洛谷 |https://www.luogu.com.cn/problem/P5707 题目介绍 题目描述 学校和 yyy 的家之间的距离为 s 米,而 yyy 以v 米每分钟的速度匀速走向学校。 在上学的路上,yyy 还要额外花费 1010 分钟的时间进行垃圾分…

RHCE---时间/远程连接服务器

文章目录 目录 文章目录 前言 一.安装时间服务器软件 初始化系统 二.配置时间服务器的服务端 三.配置时间服务器的客户端 四.远程连接服务器 前言 Linux中的时间服务器是指NTP服务器,NTP是Network Time Protocol的缩写,即网络时间协议。NTP服务器可以…

工业互联网:数字化革命的引擎

工业互联网,作为数字化革命的引擎,正以前所未有的速度和力度改变着我们的世界。这一概念不再局限于企业内部的信息技术应用,而是将互联网、大数据、人工智能等技术深度融入到制造业、能源、交通、农业等各个领域,实现了设备、系统…

竞赛选题 基于深度学的图像修复 图像补全

1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学的图像修复 图像补全 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-se…

项目管理中,产品经理如何合理分配任务?

大部分工作在软件行业中的分配是明确的,例如开发人员负责编写代码,产品经理负责编写文档,设计师负责绘制图形。然而,仍有一部分工作并不明确由谁负责。无论是产品经理还是开发人员都可以完成这些工作。 如果产品经理不擅长分配任…

【算法基础】数组和链表

目录 1 数组(Array) 1.1 定义和特点 1.2 基本操作 1.3 数组的时间复杂度 1.4 应用场景 2 链表(Linked List) 2.1 定义和特点: 2.1.1 单向链表(Singly Linked List) 2.1.2 双向链表&…

【iOS】引用计数与autorelease

文章目录 前言一、什么是自动引用计数二、内存管理/引用计数三、内存管理的思考方式四、release与autorelease五、赋值的引用计数 前言 最近在学习iOS内存管理之引用计数,特此撰写博客记录学习过程 一、什么是自动引用计数 自动引用计数(ARC&#xff0…

在支付宝小程序上websocket实现mqtt协议连接服务器控制硬件

概述 支付宝小程序作对外开放,有许许多多的好玩的地方,那么本文就在支付宝小程序上websocket实现mqtt协议连接服务器控制智能硬件!! 详细 一、前言; 那么本系列连载的博文,都是围绕着 支付宝小程序如何实…

9月25日星期一,早安心语早安问候语早读

1、 人生的幸福,一半要争,一半要随,争,不是与他人,而是与困苦,随,不是随波逐流,而是知止而后安,争,人生少遗憾;随,知足者常乐&…

Oracle 创建用户及模式

目录 1. 简言 2. 创建表空间 3. 创建用户与上面创建的文件形成映射关系 4. 添加权限 5. 登录 1. 简言 Oracle 创建数据库与用户一般一一对应, 准确的说可以 Oracle 中的 Schema 相当于 MySQL 中的数据库. Oracle 不支持创建自定义模式的, 想要创建模式的话只能新建一个用户…

Linux基础指令(五)

目录 前言1. 打包和压缩1.1 是什么1.2 为什么1.3 怎么办? 2. zip & unzip3. tar 指令结语: 前言 欢迎各位伙伴来到学习 Linux 指令的 第五天!!! 在上一篇文章 Linux基本指令(四) 当中,我们学习了 fin…

C++标准模板(STL)- 输入/输出操纵符-(std::endl)

操纵符是令代码能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。 不以参数调用的操纵符&#xff08;例如 std::cout << std::boolalpha; 或 std::cin >> std::hex; &#xff09;实现为接受到流的引用为其唯一参数的函数。 basic_ostream::…

计算机毕设 基于大数据的抖音短视频数据分析与可视化 - python 大数据 可视化

文章目录 0 前言1 课题背景2 数据清洗3 数据可视化地区-用户观看时间分界线每周观看观看路径发布地点视频时长整体点赞、完播 4 进阶分析相关性分析留存率 5 深度分析客户价值判断 5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;…

微信小程序的无限瀑布流写法

微信小程序的无限瀑布流实现总算做完了&#xff0c;换了好几种方法&#xff0c;过程中出现了各种BUG。 首先官方有瀑布流的插件&#xff08;Skyline /grid-view&#xff09;&#xff0c;不是原生的我就不想引入&#xff0c;因为我的方块流页面已经搭好了&#xff0c;引入说不定…

时空智友企业流程化管控系统任意文件上传漏洞复现【附POC】

文章目录 时空智友企业流程化管控系统任意文件上传漏洞复现0x01 前言0x02 漏洞描述0x03 影响平台0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现4.访问shell地址 0x06 修复建议 时空智友企业流程化管控系统任意文件上传漏洞复现 0x01 前言 免责声明&#xff1a;请…

股票难还是期货难?国内玩期货的人多吗?

股票和期货都是相对较难的金融投资工具。它们都有各自的优点和挑战&#xff0c;而且都需要深入了解市场、制定策略和进行风险管理。 就难度而言&#xff0c;期货和股票的难度主要在于以下方面&#xff1a; 1. 市场风险&#xff1a;股票和期货市场都存在风险&#xff0c;包括价格…

【沐风老师】3DMAX翻转折叠动画插件FoldFx使用方法详解

3DMAX翻转折叠动画插件FoldFx使用方法详解 3DMAX翻转折叠动画插件FoldFx&#xff0c;是3dMax运动图形工具&#xff0c;用于创建多边形折叠动画。用户几乎有无限的可能性&#xff0c;因为动画的每个方面都是可控的。 【适用版本】 适用于3dMax版本&#xff1a;2010及更新版本&a…