日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

spring aop 环绕通知around和其他通知的区别

發(fā)布時(shí)間:2024/4/13 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring aop 环绕通知around和其他通知的区别 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言:

?????spring?的環(huán)繞通知和前置通知,后置通知有著很大的區(qū)別,主要有兩個(gè)重要的區(qū)別:

1)?目標(biāo)方法的調(diào)用由環(huán)繞通知決定,即你可以決定是否調(diào)用目標(biāo)方法,而前置和后置通知???是不能決定的,他們只是在方法的調(diào)用前后執(zhí)行通知而已,即目標(biāo)方法肯定是要執(zhí)行的。

2)??環(huán)繞通知可以控制返回對(duì)象,即你可以返回一個(gè)與目標(biāo)對(duì)象完全不同的返回值,雖然這很危險(xiǎn),但是你卻可以辦到。而后置方法是無(wú)法辦到的,因?yàn)樗窃谀繕?biāo)方法返回值后調(diào)用

?? 這里是經(jīng)過(guò)我自己測(cè)試的過(guò)的例子,使用面向切面來(lái)處理一些問(wèn)公共的問(wèn)題,比如,權(quán)限管理,事務(wù)的委托

下面的例子就是使用環(huán)繞通知,當(dāng)程序發(fā)生異常時(shí),重復(fù)提交請(qǐng)求,重復(fù)的次數(shù)是可以設(shè)定的

??? 當(dāng)我們開(kāi)發(fā)企業(yè)級(jí)應(yīng)用時(shí),通常會(huì)想要從幾個(gè)切面來(lái)引用模塊化的應(yīng)用和特定操作的集合,下面是一個(gè)典型的通用切面,看起來(lái)可能像下面這樣(這也是Spring文檔里的)

?

package test.prefer.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SystemArchitecture {

? /**
?? * A join point is in the web layer if the method is defined
?? * in a type in the com.xyz.someapp.web package or any sub-package
?? * under that.
?? */
? @Pointcut("within(com.xyz.someapp.web..*)")
? public void inWebLayer() {}

? /**
?? * A join point is in the service layer if the method is defined
?? * in a type in the com.xyz.someapp.service package or any sub-package
?? * under that.
?? */
? @Pointcut("within(com.xyz.someapp.service..*)")
? public void inServiceLayer(){}

? /**
?? * A join point is in the data access layer if the method is defined
?? * in a type in the com.xyz.someapp.dao package or any sub-package
?? * under that.
?? */
? @Pointcut("within(com.xyz.someapp.dao..*)")
? public void inDataAccessLayer(){}

? /**
?? * A business service is the execution of any method defined on a service
?? * interface. This definition assumes that interfaces are placed in the
?? * "service" package, and that implementation types are in sub-packages.
?? *?
?? * If you group service interfaces by functional area (for example,?
?? * in packages com.xyz.someapp.abc.service and com.xyz.def.service) then
?? * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
?? * could be used instead.
?? *
?? * Alternatively, you can write the expression using the 'bean'
?? * PCD, like so "bean(*Service)". (This assumes that you have
?? * named your Spring service beans in a consistent fashion.)
?? */
? @Pointcut("execution(* test.prefer.aspect.*.*(..))")
? public void businessService(){}
??
? /**
?? * A data access operation is the execution of any method defined on a?
?? * dao interface. This definition assumes that interfaces are placed in the
?? * "dao" package, and that implementation types are in sub-packages.
?? */
? @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
? public void dataAccessOperation(){}

}

?

?一、定義自己的一個(gè)切面

/*
*文件名:ConcurrentOperationExecutor.Java
*描述:<描述>
*修改人:Administrator
*/

package test.prefer.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;

/**
?* @author?
?*@date?2010-6-1
?*/
@Aspect
public class ConcurrentOperationExecutor implements Ordered {
???
?? private static final int DEFAULT_MAX_RETRIES = 2;

?? private int maxRetries = DEFAULT_MAX_RETRIES;
?? private int order = 1;

?? public void setMaxRetries(int maxRetries) {
????? this.maxRetries = maxRetries;
?? }
???
?? public int getOrder(){
????? return this.order;
?? }
?? public void setOrder(int order){
????? this.order = order;
?? }
???
?? @Around("test.prefer.aspect.SystemArchitecture.businessService()")
?? public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {?
??? //環(huán)繞通知處理方法
????? int numAttempts = 0;
????? Exception lockFailureException;
????? do {
???????? numAttempts++;
???????? try {?
??????? ? System.out.println("環(huán)繞通知方法[ doConcurrentOperation(ProceedingJoinPoint pjp) ].............");
??????????? return pjp.proceed();
???????? }
???????? catch(Exception ex) {
??????????? lockFailureException = ex;
???????? }
????? }
????? while(numAttempts <= this.maxRetries);
????? throw lockFailureException;
?? }

}

?

說(shuō)明:

??? 請(qǐng)注意切面實(shí)現(xiàn)了?Ordered?接口,這樣我們就可以把切面的優(yōu)先級(jí)設(shè)定為高于事務(wù)通知 (我們每次重試的時(shí)候都想要在一個(gè)全新的事務(wù)中進(jìn)行)。maxRetries和order?屬性都可以在Spring中配置。主要的動(dòng)作在doConcurrentOperation這個(gè)環(huán)繞通知方法中發(fā)生。 請(qǐng)注意這個(gè)時(shí)候我們所有的businessService()方法都會(huì)使用這個(gè)重試策略。 我們首先會(huì)嘗試處理,如果得到一個(gè)Exception異常, 我們僅僅重試直到耗盡所有預(yù)設(shè)的重試次數(shù)(spring開(kāi)發(fā)文檔)

?

二、在配置文件里配置這個(gè)切面

<aop:aspectj-autoproxy/>

<bean id="concurrentOperationExecutor"
? class="test.prefer.aspect.ConcurrentOperationExecutor">
???? <property name="maxRetries" value="3"/>
???? <property name="order" value="100"/>??
</bean>

?

好了,下面我們就試一下效果吧

?

三、測(cè)試效果

??? 1)新建一個(gè)測(cè)試的bean: MyTestAspect,代碼如下:

package test.prefer.aspect;
/**
?* 這是一個(gè)切面類
?*/
import org.aspectj.lang.annotation.Aspect;

public class MyTestAspect {
?int k=0;
?public void test(String args) throws Exception{
??System.out.println("這里是[ 目標(biāo) ]方法test()"+ ++k);
??if(k<2){
???throw new Exception();
??}
??
?}

}

?

這個(gè)類必須在連接點(diǎn)的包或者子包下面,

在SystemArchitecture里有定義

?@Pointcut("execution(* test.prefer.aspect.*.*(..))")
? public void businessService(){}

?

2)applicationContext.xml里配置 MyTestAspect

<bean id="test" class="test.prefer.aspect.MyTestAspect"/>

?

3)好了,看看效果吧

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.prefer.aspect.MyTestAspect;

public class example {
?
?public static void main(String args[]){
??
??ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
??MyTestAspect t =(MyTestAspect)ctx.getBean("test");
??try{
??t.test("");
??}catch(Exception e){
???System.out.println("main()中處理異常"+e);
??}
?}

}

輸出結(jié)果是:

環(huán)繞通知方法[ doConcurrentOperation(ProceedingJoinPoint pjp) ].............
這里是[ 目標(biāo) ]方法test()1
環(huán)繞通知方法[ doConcurrentOperation(ProceedingJoinPoint pjp) ].............
這里是[ 目標(biāo) ]方法test()

總結(jié)

以上是生活随笔為你收集整理的spring aop 环绕通知around和其他通知的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。