Java注解方式实现aop,切点切面实战

news2024/11/26 6:22:04

注解方式实现aop我们主要分为如下几个步骤(有更好的方法的话,欢迎交流):

1.在切面类(为切点服务的类)前用@Aspect注释修饰,声明为一个切面类。

2.用@Pointcut注释声明一个切点,目的是为了告诉切面,谁是它的服务对象。(此注释修饰的方法的方法体为空,不需要写功能比如 public void say(){};就可以了,方法名可以被候命的具体服务功能所以引用,它可以被理解为切点对象的一个代理对象方法)

3.在对应的方法前用对应的通知类型注释修饰,将对应的方法声明称一个切面功能,为了切点而服务

4.在spring配置文件中开启aop注释自动代理。如:<aop:aspectj-autoproxy/>

可能很抽象,那么废话不多说,代码如下:

1、创建你的业务方法(切点方法)

package com.lnj.aop;

import org.springframework.stereotype.Component;

@Component("knight")
public class BraveKnight {
    public void saying(){
        System.out.println("我是业务方法类..(切点方法)");
    }
}

2、切面类:(注释主要在这里体现)

package com.lnj.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


/**
 * 注解方式声明aop
 * 1.用@Aspect注解将类声明为切面(如果用@Component("")注解注释为一个bean对象,那么就要在spring配置文件中开启注解扫描,<context:component-scan base-package="com.lnj.aop"/>
 *      否则要在spring配置文件中声明一个bean对象)
 * 2.在切面需要实现相应方法的前面加上相应的注释,也就是通知类型。
 * 3.此处有环绕通知,环绕通知方法一定要有ProceedingJoinPoint类型的参数传入,然后执行对应的proceed()方法,环绕才能实现。
 */
@Component("annotationTest")
@Aspect
public class AnnotationTest {
    //定义切点
    @Pointcut("execution(* *.saying(..))")
    public void sayings(){}
    /**
     * 前置通知(注解中的sayings()方法,其实就是上面定义pointcut切点注解所修饰的方法名,那只是个代理对象,不需要写具体方法,
     * 相当于xml声明切面的id名,如下,相当于id="embark",用于供其他通知类型引用)
     * <aop:config>
        <aop:aspect ref="mistrel">
            <!-- 定义切点 -->
            <aop:pointcut expression="execution(* *.saying(..))" id="embark"/>
            <!-- 声明前置通知 (在切点方法被执行前调用) -->
            <aop:before method="beforSay" pointcut-ref="embark"/>
            <!-- 声明后置通知 (在切点方法被执行后调用) -->
            <aop:after method="afterSay" pointcut-ref="embark"/>
        </aop:aspect>
       </aop:config>
     */
    @Before("sayings()")
    public void sayHello(){
        System.out.println("注解类型前置通知");
    }
    //后置通知
    @After("sayings()")
    public void sayGoodbey(){
        System.out.println("注解类型后置通知");
    }
    //环绕通知。注意要有ProceedingJoinPoint参数传入。
    @Around("sayings()")
    public void sayAround(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("注解类型环绕通知..环绕前");
        pjp.proceed();//执行方法
        System.out.println("注解类型环绕通知..环绕后");
    }
}

3、spring配置文件:

<?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:context="http://www.springframework.org/schema/context"
    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.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.lnj.aop"/>
    <!-- 开启aop注解方式,此步骤s不能少,这样java类中的aop注解才会生效 -->
    <aop:aspectj-autoproxy/>
</beans>

4、启动测试代码:

package com.lnj.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("com/lnj/aop/beans.xml");
        BraveKnight br = (BraveKnight) ac.getBean("knight");
        br.saying();
    }
}

运行结果:

注解类型环绕通知..环绕前
注解类型前置通知
我是业务方法类..(切点方法)
注解类型环绕通知..环绕后
注解类型后置通知

========================分割线===================================
  因为使用了注解方式,所以配置文件少了很多内容,只需要一句<context:component-scan base-package="com.lnj.aop"/>声明要扫描的包,框架会自动扫描注释并生成bean对象。有个@Component("knight")这个注释,和<bean id="knight" class="com.lnj.aop.BraveKnight"/>这个配置时一样的意思,框架会自动识别并创建名为knight的BraveKnight对象。所以有了注释,只需要开启注释扫描配置就好了,无需再做相同的bean配置。

如果运行过程中出现Spring aop : error at ::0 can't find referenced pointcut sleepPonit的错误,那么很可能是spring的包的版本问题,

工程目录如下:

通知注解类型如下:

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

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

相关文章

STM32 10个工程篇:1.IAP远程升级(三)

本想着周六去更新IAP远程升级&#xff08;三&#xff09;&#xff0c;但是周三单位突然通知团建周六去爬水长城&#xff0c;晚上回来已经精疲力竭&#xff0c;打开电脑不由地点开网易云音乐听着听着感觉很乏&#xff0c;去床上躺了会可一觉醒来已经夜里三点&#xff0c;于是调整…

【人工智能】— 贝叶斯网络、概率图模型、全局语义、因果链、朴素贝叶斯模型、枚举推理、变量消元

【人工智能】— 贝叶斯网络 频率学派 vs. 贝叶斯学派贝叶斯学派Probability&#xff08;概率&#xff09;:独立性/条件独立性&#xff1a;Probability Theory&#xff08;概率论&#xff09;:Graphical models &#xff08;概率图模型&#xff09;什么是图模型&#xff08;Grap…

深度学习之图像分类识别(一):AlexNet

本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;MobileNet&#xff0c…

基于matlab使用麦克风阵列进行声波束成形

一、前言 此示例说明了麦克风阵列波束成形&#xff0c;以便在干扰为主的嘈杂环境中提取所需的语音信号。此类操作可用于增强语音信号质量以进行感知或进一步处理。例如&#xff0c;嘈杂的环境可以是交易室&#xff0c;麦克风阵列可以安装在交易计算机的显示器上。如果交易计算机…

js绘制的红心

看腻歪了粒子特效的红心&#xff0c;今天给各位整个线条的&#xff0c;效果图如下&#xff1a; 表白显圣神器&#xff0c;你值得拥有&#xff0c;代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…

必定收藏:国内免费可用 ChatGPT 网页版

ChatGPT是一个基于人工智能的聊天机器人&#xff0c;它可以与用户进行自然语言交互。ChatGPT使用了最新的自然语言处理技术&#xff0c;包括深度学习和神经网络&#xff0c;以便更好地理解用户的意图和回答用户的问题。 ChatGPT可以回答各种问题&#xff0c;包括但不限于常见问…

Cesium入门之七:Cesium加载地形数据

Cesium加载地形数据 一、什么是地形数据二、TerrainProvider类常用属性常用方法 三、TerrainProvider子类CesiumTerrainProvider类常用属性常用方法 CustomHeightmapTerrainProvider类ArcGISTiledElevationTerrainProvider类常用属性常用方法 EllipsoidTerrainProvider类常用属…

bash shell脚本常用代码记录

任何编程语言&#xff0c;常用的语法和代码结构其实不多的&#xff0c;如果为了快速的掌握入手一门编程语言&#xff0c;我认为只需要把该语言的常见语法和代码记下来&#xff0c;再结合实际需求去拼接成新的代码。这篇博客主要是记录bash shell的一些用法&#xff0c;便于日后…

机器学习指标: F1分数

动动发财的小手&#xff0c;点个赞吧&#xff01; F1 score 简介 在本文[1]中&#xff0c;您将了解 F1 分数。 F1 分数是一种机器学习指标&#xff0c;可用于分类模型。尽管分类模型存在许多指标&#xff0c;但通过本文&#xff0c;您将了解 F1 分数的计算方式以及何时使用它有…

腾讯云语音合成

用腾讯云 AI 语音合成打造有声书制作工具 代码开发 第一步&#xff1a;电子书文件解析 第二步&#xff1a;有声语音合成 第三步&#xff1a;完成有声书制作脚本 第四步&#xff1a;脚本可视化 产品体验 腾讯云 AI 语音合成服务已经非常成熟&#xff0c;基于开源工具整合 TTS P…

JAVA135-185

JAVA135-185 多线程多线程成员方法线程优先级eg&#xff0c;卖票&#xff08;线程的安全问题&#xff09;需要解决线程同时抢的问题 同步方法LOCK锁等待唤醒机制阻塞队列实现等待唤醒机制多线程的六种状态红包抽奖箱抽奖比较 线程池最大并行数网络编程InetAdress端口号协议练习…

Mutipart

含义&#xff1a; 多部分的、复合 场景&#xff1a; 位置&#xff1a;package org.springframework.boot.autoconfigure.web.servlet; Springboot中autoconfigration包下web包下servlet下DispatcherServletAutoConfiguration中&#xff1a; 有一个默认加载的Bean Bean …

stm32通用外部spi下载算法实现

参考硬汉嵌入式&#xff1a;【实战技能】任何支持SWD接口的单片机都可以方便移植的SPI Flash烧写算法制作_哔哩哔哩_bilibili 该up主提供的stm32H7的模板工程&#xff0c;目前需求是实现基于正点原子探索者stm32f407zet6W25Q128 下载算法实现步骤 使用cubemx建立一个LED工程…

postgresql walsender源码分析

专栏内容&#xff1a;postgresql内核源码分析个人主页&#xff1a;我的主页座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物&#xff0e; 目录 前言 介绍 数据结构 WAL对端的状态 walsender进程 WALsender交互流程 在…

【连续介质力学】张量分量的变换定律

张量分量的变换定律 张量的分量是依赖于坐标系的&#xff0c;所以当坐标系发生旋转&#xff0c;张量分量也会发生改变&#xff0c;张量分量与坐标系通过分量变换规律互相关联起来的。 考虑在正交基 ( e ^ 1 , e ^ 2 , e ^ 3 ) (\hat e_1, \hat e_2, \hat e_3) (e^1​,e^2​,…

【51单片机】串口通信使用串口通信控制LED灯

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【51单片机】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 &#x1f354;串口通信 &#x1f60e;代码…

HTTP1.1(四)URI

一 URI的基本格式以及与URL的区别 ① URI直观感受 1&#xff09;URI是HTTP协议的重要组成部分2&#xff09;ABNF如何严格定义URI ② URL、URN、URI ③ URI细讲 ④ URI的组成 ⑤ ABNF关于URI定义 blob:http 地址的原理及生成方法 video 标签 src 带有blob:http data…

NetCore发布到Docker-单机

一.git安装 1.下载 https://github.com/git/git/releases/tag/v2.40.1 2.将本地的安装包上传到 linux 服务器上&#xff0c;我这里放在 /opt/git/ 目录下 3.解压压缩包&#xff0c;得到目录 git-2.40.1&#xff0c;位置在 /opt/git/git-2.40.1 tar -zxvf git-2.40.1.tar.gz 4.…

【刷题之路】LeetCode 225. 用队列实现栈

【刷题之路】LeetCode 225. 用队列实现栈 一、题目描述二、解题1、主要思路解析2、先实现栈3、实现各个接口3.1、初始化接口3.2、push接口3.3、pop接口3.4、myStackTop接口3.5、myStackEmpty接口3.6、myStackFree接口 一、题目描述 原题连接&#xff1a; 225. 用队列实现栈 题…

如何选择合适的自动化测试工具? 我教你

目录 前言 选择最佳自动化测试工具的重要性 自动化测试工具的种类 选择自动化测试工具时要考虑的因素 自动化测试工具的选择标准 前言 自动化测试是高质量软件交付领域中最重要的实践之一。在今天的敏捷开发方法中&#xff0c;几乎任一软件开发过程都需要在开发阶段的某个…