电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Spring AOP 切面@Around注解的用法說明

瀏覽:19日期:2023-07-23 08:40:06

@Around注解可以用來在調用一個具體方法前和調用后來完成一些具體的任務。

比如我們想在執行controller中方法前打印出請求參數,并在方法執行結束后來打印出響應值,這個時候,我們就可以借助于@Around注解來實現;

再比如我們想在執行方法時動態修改參數值等

類似功能的注解還有@Before等等,用到了Spring AOP切面思想,Spring AOP常用于攔截器、事務、日志、權限驗證等方面。

完整演示代碼如下:

需要說明的是,在以下例子中,我們即可以只用@Around注解,并設置條件,見方法run1();也可以用@Pointcut和@Around聯合注解,見方法pointCut2()和run2(),這2種用法是等價的。如果我們還想利用其進行參數的修改,則調用時必須用joinPoint.proceed(Object[] args)方法,將修改后的參數進行回傳。如果用joinPoint.proceed()方法,則修改后的參數并不會真正被使用。

import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component; import javax.persistence.EntityManager; /** * 控制器切面 * * @author lichuang */ @Component@Aspectpublic class ControllerAspect { private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class); @Autowired private EntityManager entityManager; /** * 調用controller包下的任意類的任意方法時均會調用此方法 */ @Around('execution(* com.company.controller.*.*(..))') public Object run1(ProceedingJoinPoint joinPoint) throws Throwable { //獲取方法參數值數組 Object[] args = joinPoint.getArgs(); //得到其方法簽名 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); //獲取方法參數類型數組 Class[] paramTypeArray = methodSignature.getParameterTypes(); if (EntityManager.class.isAssignableFrom(paramTypeArray[paramTypeArray.length - 1])) { //如果方法的參數列表最后一個參數是entityManager類型,則給其賦值 args[args.length - 1] = entityManager; } logger.info('請求參數為{}',args); //動態修改其參數 //注意,如果調用joinPoint.proceed()方法,則修改的參數值不會生效,必須調用joinPoint.proceed(Object[] args) Object result = joinPoint.proceed(args); logger.info('響應結果為{}',result); //如果這里不返回result,則目標對象實際返回值會被置為null return result; } @Pointcut('execution(* com.company.controller.*.*(..))') public void pointCut2() {} @Around('pointCut2()') public Object run2(ProceedingJoinPoint joinPoint) throws Throwable { //獲取方法參數值數組 Object[] args = joinPoint.getArgs(); //得到其方法簽名 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); //獲取方法參數類型數組 Class[] paramTypeArray = methodSignature.getParameterTypes(); if (EntityManager.class.isAssignableFrom(paramTypeArray[paramTypeArray.length - 1])) { //如果方法的參數列表最后一個參數是entityManager類型,則給其賦值 args[args.length - 1] = entityManager; } logger.info('請求參數為{}',args); //動態修改其參數 //注意,如果調用joinPoint.proceed()方法,則修改的參數值不會生效,必須調用joinPoint.proceed(Object[] args) Object result = joinPoint.proceed(args); logger.info('響應結果為{}',result); //如果這里不返回result,則目標對象實際返回值會被置為null return result; }}

補充:Spring Aop實例(AOP 如此簡單)@Aspect、@Around 注解方式配置

IoC相關的基本內容告一段落,本次介紹Spring的第二個特性,AOP,面向切面編程,術語聽起來比較不容易理解,沒關系,一切盡在實例中,讓我們看一個簡單的實例,就能明白。

實例

項目工程目錄結構和代碼獲取地址

獲取地址(版本Log將會注明每一個版本對應的課程)

https://github.com/laiyijie/SpringLearning

目錄結構

Spring AOP 切面@Around注解的用法說明

運行工程

運行具有Main函數的 App.java

得到如下輸出

method start time:1480223298250userHellomethod end time:1480223299250項目詳解

從App.java入手

App.java

package me.laiyijie.demo;import org.springframework.context.support.ClassPathXmlApplicationContext;import me.laiyijie.demo.service.HelloInterface;public class App { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext('root-context.xml'); HelloInterface userService = context.getBean(HelloInterface.class); userService.sayHello(); context.close(); }}

調用的是HelloInterface的sayHello方法

HelloInterface.java

package me.laiyijie.demo.service;public interface HelloInterface{ void sayHello(); }

其實現類為UserServiceImpl.java

UserServiceImpl.java

package me.laiyijie.demo.service;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl implements HelloInterface { public void sayHello() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println('userHello'); } }

誒?情況跟我們看到的代碼有出入?

sayHello 應該只輸出 userHello,前后兩行輸出從何出現?

在Main函數中找不到一點兒線索!

這就是AOP的一個強大特性:

無侵入性,不改變原有的代碼,卻能增加功能!

那么究竟是如何增加功能的呢?

讓我們看看TimeMonitor.java

TimeMonitor.java

package me.laiyijie.demo.aop;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Service;@Service@Aspectpublic class TimeMonitor { @Around('execution(* me.laiyijie.demo.service.UserServiceImpl.sayHello(..))') public void monitorAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println('method start time:' + System.currentTimeMillis()); Object re = pjp.proceed(); System.out.println('method end time:' + System.currentTimeMillis()); }}

終于看到了 method start time:1480223298250 和 method end time:1480223299250這兩行輸出是從哪兒出現的了!

讓我們來仔細解讀一下這個類

類有兩個注釋,分別是@Service和@Aspect,第一個注解是使得TimeMonitor受Spring托管并實例化。@Aspect就是使得這個類具有AOP功能(你可以這樣理解)兩個注解缺一不可

類里面只有一個方法,名字叫做monitorAroud,其實就是為了檢測函數執行時間的!

那么關鍵點來了,兩個輸出語句是怎么插入到sayHello方法的前后的呢!

看這個注解:

@Around('execution(* me.laiyijie.demo.service.UserServiceImpl.sayHello(..))')

@Around表示包圍一個函數,也就是可以在函數執行前做一些事情,也可以在函數執行后做一些事情

execution(* me.laiyijie.demo.service.UserServiceImpl.sayHello(..))

這個比較好理解,就是使用表達式的方式指定了要對哪個函數進行包圍!(除了execution以外還有很多,可以搜索AspectJ語法來學習)

也就是說,這個注解完整的說明了,應該在函數的什么位置插入變化,也就是所謂的切點

之后是函數的定義:

public Object monitorAround(ProceedingJoinPoint pjp)

這里引入了ProceedingJoinPoint,在使用了@Around之后可以帶入這個參數,代表的其實就是sayHello這個函數,不過做了一些封裝

而 Object re = pjp.proceed(); 就是相當于執行了 sayHello方法!

剩下的代碼就不用過多解釋了,就是在執行這個函數的前后分別進行了系統時間的獲取。

我們把這個函數體,也就是定義了要做那些事情的代碼,稱作增強

而包含切點和增強結合起來就稱作切面

面向切面由此而來!

Spring AOP 開啟需要的配置

需要配置兩項

1、pom.xml增加依賴(因為要用到AOP還需要不同的JAR包)

2、root-context.xml中增加切面相關配置

root-context.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: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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd'> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <context:component-scan base-package='me.laiyijie.demo'></context:component-scan></beans>

root-context.xml 增加了兩行

1、xmlns:aop='http://www.springframework.org/schema/aop'

代表加入命名空間

2、<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

使用1中引入的aop命名空間開起自動代理(自動代理具體含義后續慢慢解釋,簡單的理解就是AOP的實現是依靠自動代理實現的)

pom.xml

<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'> <modelVersion>4.0.0</modelVersion> <groupId>me.laiyijie</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency> </dependencies></project>

增加了一個依賴

AspectJ 一個強大的AOP框架,也就是@Aspect和@Around以及ProceedingJoinPoint這些注解和方法的提供者

小結

增強:定義了應該怎么把額外的動作加入到指定函數中

切點:定義了你應該把增強插入到哪個函數的什么位置

切面:切點和增強組合起來的稱呼

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。如有錯誤或未考慮完全的地方,望不吝賜教。

標簽: Spring
相關文章:
主站蜘蛛池模板: 智慧农业|农业物联网|现代农业物联网-托普云农物联网官方网站 | 捆扎机_气动捆扎机_钢带捆扎机-沈阳海鹞气动钢带捆扎机公司 | 台湾Apex减速机_APEX行星减速机_台湾精锐减速机厂家代理【现货】-杭州摩森机电 | 药品仓库用除湿机-变电站用防爆空调-油漆房用防爆空调-杭州特奥环保科技有限公司 | 泡沫消防车_水罐消防车_湖北江南专用特种汽车有限公司 | 导电银胶_LED封装导电银胶_半导体封装导电胶厂家-上海腾烁 | 成都治疗尖锐湿疣比较好的医院-成都治疗尖锐湿疣那家医院好-成都西南皮肤病医院 | 艾默生变频器,艾默生ct,变频器,ct驱动器,广州艾默生变频器,供水专用变频器,风机变频器,电梯变频器,艾默生变频器代理-广州市盟雄贸易有限公司官方网站-艾默生变频器应用解决方案服务商 | 房屋质量检测-厂房抗震鉴定-玻璃幕墙检测-房屋安全鉴定机构 | 华东师范大学在职研究生招生网_在职研究生招生联展网 | 水质监测站_水质在线分析仪_水质自动监测系统_多参数水质在线监测仪_水质传感器-山东万象环境科技有限公司 | 工控机,嵌入式主板,工业主板,arm主板,图像采集卡,poe网卡,朗锐智科 | PSI渗透压仪,TPS酸度计,美国CHAI PCR仪,渗透压仪厂家_价格,微生物快速检测仪-华泰和合(北京)商贸有限公司 | 武汉宣传片制作-视频拍摄-企业宣传片公司-武汉红年影视 | 电子厂招聘_工厂招聘_普工招聘_小时工招聘信息平台-众立方招工网 | 众品地板网-地板品牌招商_地板装修设计_地板门户的首选网络媒体。 | 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 扬州汇丰仪表有限公司| 冲锋衣滑雪服厂家-冲锋衣定制工厂-滑雪服加工厂-广东睿牛户外(S-GERT) | 苏州注册公司_苏州代理记账_苏州工商注册_苏州代办公司-恒佳财税 | 自动检重秤-动态称重机-重量分选秤-苏州金钻称重设备系统开发有限公司 | 驾驶式洗地机/扫地机_全自动洗地机_工业洗地机_荣事达工厂官网 | 心肺复苏模拟人|医学模型|急救护理模型|医学教学模型上海康人医学仪器设备有限公司 | 并网柜,汇流箱,电控设备,中高低压开关柜,电气电力成套设备,PLC控制设备订制厂家,江苏昌伟业新能源科技有限公司 | 办公室家具_板式办公家具定制厂家-FMARTS福玛仕办公家具 | 急救箱-应急箱-急救包厂家-北京红立方医疗设备有限公司 | 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 | 全自动五线打端沾锡机,全自动裁线剥皮双头沾锡机,全自动尼龙扎带机-东莞市海文能机械设备有限公司 | 大巴租车平台承接包车,通勤班车,巴士租赁业务 - 鸿鸣巴士 | 密集架-手摇-智能-移动-价格_内蒙古档案密集架生产厂家 | 苏州工作服定做-工作服定制-工作服厂家网站-尺品服饰科技(苏州)有限公司 | ERP企业管理系统永久免费版_在线ERP系统_OA办公_云版软件官网 | 诗词大全-古诗名句 - 古诗词赏析| 多功能干燥机,过滤洗涤干燥三合一设备-无锡市张华医药设备有限公司 | 杭州网络公司_百度SEO优化-外贸网络推广_抖音小程序开发-杭州乐软科技有限公司 | 云南标线|昆明划线|道路标线|交通标线-就选云南云路施工公司-云南云路科技有限公司 | 啤酒设备-小型啤酒设备-啤酒厂设备-济南中酿机械设备有限公司 | 河南15年专业网站建设制作设计,做网站就找郑州启凡网络公司 | 安徽控制器-合肥船用空调控制器-合肥家电控制器-合肥迅驰电子厂 安徽净化板_合肥岩棉板厂家_玻镁板厂家_安徽科艺美洁净科技有限公司 | 冷凝水循环试验箱-冷凝水试验箱-可编程高低温试验箱厂家-上海巨为(www.juweigroup.com) | 天长市晶耀仪表有限公司 |