解釋就懶得寫了,有代碼運行一下就知道了,jar除了Spring所必備的以外還要加上bsh-1.2b7.jar
- packagecom.test;
- /**
- *在線圖書銷售系統業務邏輯接口
- */
- publicinterfaceBookBiz{
- publicfloat[]buy(StringuserName,StringbookName,doubleprice);
- publicvoidcomment(StringuserName,Stringcomments);
- }
- packagecom.test;
- publicclassBookBizImplimplementsBookBiz{
- /**
- *購買圖書
- */
- publicfloat[]buy(StringuserName,StringbookName,doubleprice){
- System.out.println("業務方法buy開始執行");
- System.out.println("·"+userName+"購買圖書:"+bookName);
- System.out.println("·"+userName+"增加積分:"+(int)(price/10));
- System.out.println("·"+"向物流系統下發貨單");
- System.out.println("業務方法buy結束");
- returnnull;
- }
- /**
- *發表書評
- */
- publicvoidcomment(StringuserName,Stringcomments){
- System.out.println("業務方法comment開始執行");
- System.out.println("·"+userName+"發表書評"+comments);
- System.out.println("業務方法comment結束");
- }
- }
- packagecom.test;
- importjava.lang.reflect.Method;
- importjava.util.Arrays;
- importorg.aopalliance.intercept.MethodInterceptor;
- importorg.aopalliance.intercept.MethodInvocation;
- importorg.springframework.aop.AfterReturningAdvice;
- importorg.springframework.aop.MethodBeforeAdvice;
- importbsh.Interpreter;
- publicclassMyAdviceimplementsMethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor{
- /**
- *前通知
- */
- publicvoidbefore(Methodm,Object[]args,Objecttarget)
- throwsThrowable{
- System.out.println("前通知,調用的方法:"+m.getName()+",參數:"+Arrays.toString(args));
- }
- /**
- *後通知
- */
- publicvoidafterReturning(Objectonject,Methodmethod,Object[]args,
- Objectarg3)throwsThrowable{
- System.out.println("後通知,調用的方法:"+method.getName()+",參數:"+Arrays.toString(args));
- }
- /**
- *環繞通知,最維強大的通知,可以控制目標方法是否執行,也可以改變方法的返回值
- */
- publicObjectinvoke(MethodInvocationmethod)throwsThrowable{
- System.out.println("[環繞通知]");
- Object[]args=method.getArguments();
- /**
- *這裏我們禁止李四發表任何的評論
- */
- if(method.getMethod().getName().equals("comment")&"李四".equals(args[0])){
- System.out.println("屏蔽李四所有的評論");
- StringreturnType=method.getMethod().getReturnType().getName();
- if("int".equals(returnType)||"long".equals(returnType)||"float".equals(returnType)||"double".equals(returnType)||"byte".equals(returnType)||"short".equals(returnType)){
- //利用BeanShell構造一個內置變量返回,這裏想了好久,沒有想到什麼方法可以根據
- //指定數據類型返回指定的變量
- Interpreteri=newInterpreter();
- returni.eval("("+returnType+")0");
- }elseif("boolean".equals(returnType)){
- returnfalse;
- }
- returnnull;
- }else{
- returnmethod.proceed();
- }
- }
- }
- packagecom.test;
- importorg.springframework.context.ApplicationContext;
- importorg.springframework.context.support.ClassPathXmlApplicationContext;
- publicclassAOPTest{
- /**
- *@paramargs
- */
- publicstaticvoidmain(String[]args){
- ApplicationContextcontext=
- newClassPathXmlApplicationContext("springAop.xml");
- BookBizbookBiz=(BookBiz)context.getBean("bookBiz");
- bookBiz.buy("張三","Spring深入潛出",50);
- bookBiz.comment("李四","《恐怖世界》一點都不恐怖,很好看!");
- bookBiz.comment("張三","《Spring深入潛出》還是寫得不錯的!");
- }
- }
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <beanid="bookBizTarget"class="com.test.BookBizImpl"/>
- <beanid="myAdvice"class="com.test.MyAdvice"/>
- <beanid="bookBiz"class="org.springframework.aop.framework.ProxyFactoryBean">
- <propertyname="proxyInterfaces">
- <value>com.test.BookBiz</value>
- </property>
- <propertyname="interceptorNames">
- <list>
- <value>myAdvice</value>
- </list>
- </property>
- <propertyname="target"ref="bookBizTarget"/>
- </bean>
- </beans>
運行AOPTest 這個類,下面是輸出結果:
[環繞通知]
前通知,調用的方法:buy,參數:[張三, Spring深入潛出, 50.0]
業務方法buy開始執行
·張三購買圖書:Spring深入潛出
·張三增加積分:5
·向物流系統下發貨單
業務方法buy結束
後通知,調用的方法:buy,參數:[張三, Spring深入潛出, 50.0]
[環繞通知]
屏蔽李四所有的評論
[環繞通知]
前通知,調用的方法:comment,參數:[張三, 《Spring深入潛出》還是寫得不錯的!]
業務方法comment開始執行
·張三發表書評《Spring深入潛出》還是寫得不錯的!
業務方法comment結束
後通知,調用的方法:comment,參數:[張三, 《Spring深入潛出》還是寫得不錯的!]
從輸出結果可以看出,環繞通知是最先開始執行的,,如果環繞通知把目標方法屏蔽了不執行,那麼後面的前後通知都不會執行