日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Spring使用AspectJ的注解式實現(xiàn)AOP面向切面編程

瀏覽:119日期:2023-07-10 09:52:55
目錄1、認(rèn)識Spring AOP1.1 AOP的簡介1.2 AOP中的概念 切入點(pointcut):2、認(rèn)識AspectJ 2.1 AspectJ的簡介2.2 Spring AOP 和 AspectJ比較2.3 Spring支持AspectJ的注解式切面編程2.4 AspectJ的注解說明3、Spring使用AspectJ實現(xiàn)日志記錄操作(1)添加相關(guān)的jar包(2)編寫攔截規(guī)則的注解(3)編寫使用注解的被攔截類(4)編寫使用方法規(guī)則的被攔截類(5)編寫切面(6)配置類(7)運(yùn)行4、SpringBoot使用AspectJ實現(xiàn)日志記錄操作(1)pom.xml文件的配置(2)編寫AOP日志注解類(3)編寫控制器用于測試(4)運(yùn)行不依賴Spring使用AspectJ達(dá)到AOP面向切面編程1.導(dǎo)入依賴2.Maven插件3.使用注解4.織入/代理1、認(rèn)識Spring AOP1.1 AOP的簡介

AOP:面向切面編程,相對于OOP面向?qū)ο缶幊獭?/p>

Spring的AOP的存在目的是為了解耦。AOP可以讓一組類共享相同的行為。在OOP中只能通過繼承類和實現(xiàn)接口,來使代碼的耦合度增強(qiáng),而且類的繼承只能為單繼承,阻礙更多行為添加到一組類上,AOP彌補(bǔ)了OOP的不足。

1.2 AOP中的概念 切入點(pointcut): 切入點(pointcut):在哪些類、哪些方法上切入。 通知(advice):在方法前、方法后、方法前后做什么。 切面(aspect):切面 = 切入點 + 通知。即在什么時機(jī)、什么地方、做什么。 織入(weaving):把切面加入對象,并創(chuàng)建出代理對象的過程。 環(huán)繞通知:AOP中最強(qiáng)大、靈活的通知,它繼承了前置和后置通知,保留了連接點原有的方法。2、認(rèn)識AspectJ 2.1 AspectJ的簡介

AspectJ是一個面向切面編程的框架,它擴(kuò)展了Java語言。AspectJ定義了AOP語法,它有一個專門的編譯器用來生成遵守Java字節(jié)編碼規(guī)范的Class文件。AspectJ還支持原生的Java,只需要加上AspectJ提供的注解即可。

2.2 Spring AOP 和 AspectJ比較

簡單地說,Spring AOP 和 AspectJ 有不同的目標(biāo)。

Spring AOP 旨在提供一個跨 Spring IoC 的簡單的 AOP 實現(xiàn),以解決程序員面臨的最常見問題。它不打算作為一個完整的 AOP 解決方案 —— 它只能應(yīng)用于由 Spring 容器管理的 Bean。

AspectJ 是原始的 AOP 技術(shù),目的是提供完整的 AOP 解決方案。它更健壯,但也比 Spring AOP 復(fù)雜得多。還值得注意的是,AspectJ 可以在所有域?qū)ο笾袘?yīng)用。

2.3 Spring支持AspectJ的注解式切面編程

(1)使用@Aspect聲明一個切面。

(2)使用@After、@Before、@Around定義建言(advice),可直接將攔截規(guī)則(切點)作為參數(shù)。

(3)其中@After、@Before、@Around參數(shù)的攔截規(guī)則為切點(PointCut),為了使切點復(fù)用,可以使用@Pointcut專門定義攔截規(guī)則,然后在@After、@Before、@Around的參數(shù)中調(diào)用。

(4)其中符合條件的每一個被攔截處為連接點(JoinPoint)。

攔截方式分為:基于注解式攔截、基于方法規(guī)則式攔截。

其中注解式攔截能夠很好地控制要攔截的粒度和獲得更豐富的信息,Spring本身在事務(wù)處理(@Transactional)和數(shù)據(jù)緩存(@Cacheable)等都使用了基于注解式攔截。

2.4 AspectJ的注解說明 @Aspect:標(biāo)記為切面類。 @Before:在切入點開始處切入內(nèi)容。 @After:在切入點結(jié)尾處切入內(nèi)容。 @AfterReturning:在切入點return內(nèi)容之后切入內(nèi)容(可以用來對處理返回值做一些加工處理)。 @Around:在切入點前后切入內(nèi)容,并自己控制何時執(zhí)行切入點自身的內(nèi)容。 @AfterThrowing:用來處理當(dāng)切入內(nèi)容部分拋出異常之后的處理邏輯。3、Spring使用AspectJ實現(xiàn)日志記錄操作

【實例】使用基于注解式攔截和基于方法規(guī)則式攔截兩種方式,實現(xiàn)模擬日志記錄操作。

(1)添加相關(guān)的jar包

添加SpringAOP支持及AspectJ依賴,pom.xml文件的配置如下:

<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>5.2.3.RELEASE</spring.version> <aspectj.version>1.9.5</aspectj.version></properties> <dependencies> <!-- Spring框架 --> <dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version> </dependency> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version> </dependency> <dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version> </dependency> <!-- Aspectj依賴 --> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>${aspectj.version}</version> </dependency> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>${aspectj.version}</version> </dependency></dependencies>(2)編寫攔截規(guī)則的注解

package com.pjb.aop;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 日志記錄注解 * @author pan_junbiao **/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface LogAction{ String name();}(3)編寫使用注解的被攔截類

package com.pjb.aop;import org.springframework.stereotype.Service;/** * 使用注解的被攔截類 * @author pan_junbiao **/@Servicepublic class DemoAnnotationService{ @LogAction(name='注解式攔截的add操作') public void add() {System.out.println('執(zhí)行新增操作'); }}(4)編寫使用方法規(guī)則的被攔截類

package com.pjb.aop;import org.springframework.stereotype.Service;/** * 使用方法規(guī)則被攔截類 * @author pan_junbiao **/@Servicepublic class DemoMethodService{ public void add() {System.out.println('執(zhí)行新增操作'); }}(5)編寫切面

package com.pjb.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.*;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component;import java.lang.reflect.Method;/** * 切面 * @author pan_junbiao * 說明: * 通過@Aspect注解聲明一個切面 * 通過@Component注解讓此切面成為Spring容器管理的Bean **/@Aspect@Componentpublic class LogAspect{ /** * 通過@Pointcut注解聲明切點 */ @Pointcut('@annotation(com.pjb.aop.LogAction)') public void annotationPointCut(){}; /** * 通過@After注解聲明一個建言,并使用@Pointcut注解定義的切點 */ @After('annotationPointCut()') public void after(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method method = signature.getMethod();LogAction logAction = method.getAnnotation(LogAction.class);//通過反射獲取注解上的屬性,然后做日志記錄的相關(guān)操System.out.println('[日志記錄]注解式攔截,'+logAction.name()); } /** * 通過@Before注解聲明一個建言,此建言直接使用攔截規(guī)則作為參數(shù) */ @Before('execution(* com.pjb.aop.DemoMethodService.*(..))') public void before(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method method = signature.getMethod();System.out.println('[日志記錄]方法規(guī)則式攔截,'+method.getName()); }}(6)配置類

package com.pjb.aop;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;/** * 配置類 * @author pan_junbiao * 說明: * 使用@EnableAspectJAutoProxy注解開啟Spring對AspectJ的支持 **/@Configuration@ComponentScan('com.pjb.aop')@EnableAspectJAutoProxypublic class AopConfig{}(7)運(yùn)行

package com.pjb.aop;import org.springframework.context.annotation.AnnotationConfigApplicationContext;/** * 測試類 * @author pan_junbiao **/public class AopTest{ public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);DemoMethodService demoMethodService = context.getBean(DemoMethodService.class); demoAnnotationService.add();System.out.println('=======================================');demoMethodService.add(); context.close(); }}

執(zhí)行結(jié)果:

Spring使用AspectJ的注解式實現(xiàn)AOP面向切面編程

4、SpringBoot使用AspectJ實現(xiàn)日志記錄操作

【示例】SpringBoot項目中使用AspectJ實現(xiàn)日志記錄操作。

(1)pom.xml文件的配置

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>(2)編寫AOP日志注解類

package com.pjb.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest; /** * AOP管理日志 * @author pan_junbiao **/@Aspect@Componentpublic class AopLog{ private Logger logger = LoggerFactory.getLogger(this.getClass()); //線程局部的變量,用于解決多線程中相同變量的訪問沖突問題 ThreadLocal<Long> startTime = new ThreadLocal<>(); //定義切點 @Pointcut('execution(public * com.pjb..*.*(..))') public void aopWebLog() { } //使用@Before在切入點開始處切入內(nèi)容 @Before('aopWebLog()') public void doBefore(JoinPoint joinPoint) throws Throwable {startTime.set(System.currentTimeMillis());// 接收到請求,記錄請求內(nèi)容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest(); // 記錄下請求內(nèi)容logger.info('URL : ' + request.getRequestURL().toString());logger.info('HTTP方法 : ' + request.getMethod());logger.info('IP地址 : ' + request.getRemoteAddr());logger.info('類的方法 : ' + joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName());//logger.info('參數(shù) : ' + Arrays.toString(joinPoint.getArgs()));logger.info('參數(shù) : ' + request.getQueryString()); } //使用@AfterReturning在切入點return內(nèi)容之后切入內(nèi)容(可以用來對處理返回值做一些加工處理) @AfterReturning(pointcut = 'aopWebLog()',returning = 'retObject') public void doAfterReturning(Object retObject) throws Throwable {// 處理完請求,返回內(nèi)容logger.info('應(yīng)答值 : ' + retObject);logger.info('費(fèi)時: ' + (System.currentTimeMillis() - startTime.get())); } //使用@AfterThrowing用來處理當(dāng)切入內(nèi)容部分拋出異常之后的處理邏輯 //拋出異常后通知(After throwing advice) : 在方法拋出異常退出時執(zhí)行的通知。 @AfterThrowing(pointcut = 'aopWebLog()', throwing = 'ex') public void addAfterThrowingLogger(JoinPoint joinPoint, Exception ex) {logger.error('執(zhí)行 ' + ' 異常', ex); }}(3)編寫控制器用于測試

下面的控制器構(gòu)造了一個普通的Rest風(fēng)格的頁面。

package com.pjb.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;/** * 日志控制器 * @author pan_junbiao **/@RestControllerpublic class AopLogController{ @GetMapping('/aoptest') public String AopTest(String userName,String password) {return '您好,歡迎訪問 pan_junbiao的博客'; }}(4)運(yùn)行

啟動項目,在瀏覽器中訪問 “http://127.0.0.1:8080/aoptest?userName=pan_junbiao&password=123456”

瀏覽器執(zhí)行結(jié)果:

Spring使用AspectJ的注解式實現(xiàn)AOP面向切面編程

控制臺輸出結(jié)果:

Spring使用AspectJ的注解式實現(xiàn)AOP面向切面編程

不依賴Spring使用AspectJ達(dá)到AOP面向切面編程

網(wǎng)上大多數(shù)介紹AspectJ的文章都是和Spring容器混用的,但有時我們想自己寫框架就需要拋開Spring造輪子,類似使用原生AspectJ達(dá)到面向切面編程。步驟很簡單,只需要兩步。

1.導(dǎo)入依賴

<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.3</version></dependency>2.Maven插件

<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.10</version> <configuration><source>1.8</source><target>1.8</target><complianceLevel>1.8</complianceLevel> </configuration> <executions><execution> <goals><goal>compile</goal> </goals></execution> </executions></plugin>3.使用注解

@Aspectpublic class AspectDemo { @Pointcut('execution(* cn.yueshutong.App.say())') private void pointcut() {} // signature @Before('pointcut()') public void before(){System.out.println('Hello'); }}

App.java

public class App { public static void main( String[] args ) {System.out.println( new App().say() ); } public String say() {return 'World'; }}

這一步就和平常使用Spring AOP注解沒有什么區(qū)別了。

4.織入/代理

我們都知道,Spring AOP是通過動態(tài)代理生成一個代理類,這種方式的最大缺點就是對于對象內(nèi)部的方法嵌套調(diào)用不會走代理類,比如下面這段代碼:

@Componentpublic class TestComponent { @TestAspect public void work(){//do sth } public void call(){work(); }}

原因很簡單,對象內(nèi)部的方法調(diào)用該對象的其他方法是通過自身this進(jìn)行引用,并不是通過代理類引用。而AspectJ則不同,AspectJ是通過織入的方式將切面代碼織入進(jìn)原對象內(nèi)部,并不會生成額外的代理類。

關(guān)于這一點,我們反編譯看一下切點代碼:

//原方法 public void say() {System.out.println(this.getClass().getName());hi(); } //反編譯 public void say() {ResourceAspect.aspectOf().before();System.out.println(this.getClass().getName());this.hi(); }

深究下去,在Spring AOP中,我們只有調(diào)用代理類的切點方法才能觸發(fā)Before方法,因為代理類本質(zhì)上是對原類的一層封裝,原類是沒有變化的,原類的方法內(nèi)部的this指向的依舊是原類,這就導(dǎo)致了原類方法內(nèi)部的嵌套調(diào)用無法被代理類感知到,而AspectJ的織入就不同了,它會動態(tài)改變你的原類代碼,將Before等方法全部寫入進(jìn)你的原方法中,這就保證了面向切面編程的萬無一失。

兩種方式,各有利弊,如何使用還需要視情況而行。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲综合国产| 97se亚洲| 你懂的国产精品永久在线| 在线精品福利| 国产精品呻吟| 亚洲精品日韩久久| 日本成人在线一区| 国产精品一区免费在线| 美女视频免费精品| 国产一区二区精品久| 国产精品99在线观看| 成人亚洲一区| 青青久久av| 妖精视频成人观看www| 亚洲综合国产| 日韩二区三区四区| 久久尤物视频| 国产不卡一区| 日韩国产一区| 亚洲先锋成人| 国产一区91| 天堂俺去俺来也www久久婷婷| 欧美日韩中出| 欧美激情另类| 亚洲一区二区毛片| 欧美亚洲免费| 国内在线观看一区二区三区| 久久国产影院| 综合一区在线| 精品国产中文字幕第一页| 国产美女高潮在线观看| 91久久久精品国产| 日本成人在线视频网站| 狂野欧美性猛交xxxx| 日韩欧美精品一区| 丝袜亚洲精品中文字幕一区| 国产欧美日韩免费观看| 日韩欧美一区免费| 鲁大师成人一区二区三区| 日韩国产欧美在线视频| 精品三级在线观看视频| 欧美日韩国产亚洲一区| 国产欧美一区二区三区米奇| 久久精品123| 亚洲精品欧美| 中文字幕在线视频网站| 亚洲网址在线观看| 国产成人免费精品| 亚洲欧美日韩国产| 国产日韩一区| 亚洲黑丝一区二区| 日韩不卡免费视频| 美女一区网站| 亚洲资源网站| 国产美女高潮在线观看| 三级欧美在线一区| 成人在线黄色| 亚洲精品无吗| 久久天堂精品| 欧美激情网址| 六月婷婷一区| 亚洲欧美日韩国产一区二区| 四虎在线精品| 三级精品视频| 中文无码久久精品| 日韩av在线中文字幕| 男女男精品视频网| 天堂av在线| 日韩一区二区三区高清在线观看| 成人亚洲欧美| 欧美日韩a区| 午夜精品亚洲| 国产精品二区不卡| 日韩av电影一区| 欧美va天堂在线| 里番精品3d一二三区| 蜜桃久久av| 久久久国产精品一区二区中文| 国产亚洲精aa在线看| 91精品电影| 成人午夜在线| 国产麻豆一区| 亚洲人成亚洲精品| 亚洲性视频h| 一区二区三区四区日本视频| 欧美亚洲综合视频| 欧美专区一区二区三区| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 国产精品老牛| 日韩国产一二三区| 黄在线观看免费网站ktv| 亚洲精品影视| 亚洲成人一区| 精品丝袜在线| 麻豆国产一区| 青青草精品视频| 中文字幕一区二区三区日韩精品 | 欧美日韩xxxx| 少妇精品久久久一区二区三区| 午夜日韩av| 久久久久91| www成人在线视频| 欧美激情另类| 国产毛片精品| 日韩国产精品久久久久久亚洲| 日本大胆欧美人术艺术动态| 尤物网精品视频| 亚洲精品成人| 红桃视频国产一区| 女同性一区二区三区人了人一| 99久久久久国产精品| 亚洲国产福利| sm久久捆绑调教精品一区| 精品国产亚洲一区二区三区大结局| 国产乱码精品一区二区亚洲| 国产日产精品_国产精品毛片| 欧美一级全黄| 国产欧美日韩精品一区二区免费 | 日韩av不卡一区二区| 亚洲精品九九| 日韩欧美中文字幕在线视频| 日本一区福利在线| 少妇精品久久久| 亚洲三级观看| 日本免费一区二区视频| 久久精品99国产精品| 国产亚洲欧美日韩在线观看一区二区| 97久久亚洲| 欧美黑人做爰爽爽爽| 精品国产a一区二区三区v免费| 久久久久久婷| 日韩大片在线| 激情六月综合| 快she精品国产999| 一区二区日韩免费看| 最新亚洲国产| 国产欧美日韩视频在线 | 性欧美videohd高精| 久久精品欧美一区| 91久久久久| 日韩激情综合| 国产精品白浆| 国产欧美一区二区三区精品酒店| 日韩大片在线播放| 久久亚洲成人| 天堂成人免费av电影一区| 一二三区精品| 国产精品尤物| 欧美男人天堂| 亚洲一区二区动漫| 91综合久久爱com| 国产成人精品一区二区三区视频| 99久久久久国产精品| 亚洲一区欧美| 精品日韩一区| 亚洲成av在线| 国产精品毛片在线| 青青伊人久久| 日韩一区亚洲二区| 亚洲激情黄色| 欧美啪啪一区| 欧洲一区二区三区精品| 麻豆久久精品| 欧美aⅴ一区二区三区视频| 日韩在线看片| 亚洲一区导航| 国产一区二区三区亚洲综合| 黄色亚洲精品| 国产女人18毛片水真多18精品| 伊人久久av| 免费欧美日韩| 精品一区电影| 国产午夜久久| 老牛国内精品亚洲成av人片| 午夜av成人| 亚洲欧洲免费| 中文字幕在线高清| 亚洲精品乱码日韩| 日韩av免费大片| 亚洲精品看片| 久久精品91| 国产视频网站一区二区三区| 秋霞国产精品| 国产日韩欧美中文在线| 国产在线欧美| 美腿丝袜亚洲三区| 亚洲作爱视频| 国产一区二区三区四区二区| 国产婷婷精品| 精品国产美女a久久9999| 免费精品视频| 欧美天堂视频| 欧美色综合网| 国产亚洲一区在线| 美女av在线免费看| 欧美亚洲三级| 国产精品普通话对白| 色婷婷色综合| 日本色综合中文字幕| 九色精品91|