切面編程(帶參數)
本文系作者原創,轉載請注明出處:http://www.cnblogs.com/further-further-further/p/7786715.html
解決問題
1、分離業務監控與業務處理。簡單點說,讓開發人員更專注業務邏輯開發,類似於打印日志、統計時間、監控等等獨立成一個單獨的類,在需要的時候,動態的將代碼切入到類的指定方法上,使方法擁有更強大的功能;
2、解決代碼重復性,降低代碼復雜程度;
內容說明
1、通過@Component注解,掃描(Magician)bean並注冊到spring容器中時,需在XML配置文件中引入 <context:component-scan base-package="com.spring.example.aspectArgs"/>;
2、明確切面、切點、通知概念,這里切面是Magician,切點是Volunteer的thinkOfSomething方法,通知是Magician中所包含方法,由xml或注解配置,下面會分別給出示例;
3、通過執行Volunteer的thinkOfSomething方法,從而執行Magician中相應的方法,達到通知的效果;
應用實例:截聽志願者內心真實想法
先列出相關接口以及類代碼
切面實現接口MindReader(讀心者)
package com.spring.example.aspectAspectJArgs; //讀心者 public interface MindReader { void interceptThoughts(String thoughts); void getConclusion(String thoughts); }
切點類志願者實現接口Thinker
package com.spring.example.aspectAspectJArgs; /** * 讀心者賦予一個他需要截聽內心感應的志願者 */ public interface Thinker { void thinkOfSomething(String thoughts); }
志願者實體類Volunteer
package com.spring.example.aspectAspectJArgs; import org.springframework.stereotype.Component; /** * Created by weixw on 2017/10/24. */ @Component public class Volunteer implements Thinker { private String thoughts; @Override public void thinkOfSomething(String thoughts) { this.thoughts = thoughts; } }
以下有兩種方式實現此實例的切面編程:一、通過XML配置文件,二、AspectJ注解方式
其他代碼都相同,不同處在spring 的xml配置文件以及切面類文件
一、通過XML配置文件:
切面(讀心者)實體類
package com.spring.example.aspectArgs; /** * Created by weixw on 2017/10/24. */ import org.springframework.stereotype.Component; /** * 截聽志願者的內心感應和顯示他們在想什么 */ @Component public class Magician implements MindReader { @Override public void interceptThoughts(String thoughts) { System.out.println("Intercepting volunteer's thoughts :" +thoughts); } @Override public void getConclusion(String thoughts) { System.out.println("For your thoughts :" +thoughts); System.out.println("I think you are right."); } }
spring 配置文件 aspect-args.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.spring.example.aspectArgs"/> <aop:config> <!--通過component-scan自動掃描,@Component注解將Magician注冊到spring容器--> <aop:aspect ref="magician"> <aop:pointcut id="thinking" expression="execution(* com.spring.example.aspectArgs.Thinker.thinkOfSomething(String)) and args(thoughts)"/> <aop:before pointcut-ref="thinking" method="interceptThoughts" arg-names="thoughts"/> <aop:after pointcut-ref="thinking" method="getConclusion" arg-names="thoughts"/> </aop:aspect> </aop:config> </beans>
二 、AspectJ注解方式
切面(讀心者)實體類
package com.spring.example.aspectAspectJArgs; /** * Created by weixw on 2017/10/24. */ import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * 截聽志願者的內心感應和顯示他們在想什么 */ @Component @Aspect public class Magician implements MindReader { @Pointcut("execution(* com.spring.example.aspectAspectJArgs.Thinker.thinkOfSomething(String)) " + "&& args(thoughts)") //定義切點 public void thinkOfSomething(String thoughts){} @Before("thinkOfSomething(thoughts)") @Override public void interceptThoughts(String thoughts) { System.out.println("Intercepting volunteer's thoughts :" +thoughts); } @AfterReturning("thinkOfSomething(thoughts)") @Override public void getConclusion(String thoughts) { System.out.println("For your thoughts :" +thoughts); System.out.println("I think you are right."); } }
spring 配置文件 aspect-aspectJArgs.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.spring.example.aspectAspectJArgs"/> <aop:aspectj-autoproxy/> </beans>
測試代碼
注解測試代碼如下,配置文件測試代碼只需將配置文件名稱改成spring/aspect-args.xml即可
package com.spring.example.aspectAspectJArgs;/** * Created by weixw on 2017/10/19. */ import javafx.application.Application; import javafx.stage.Stage; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Driver extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { try { ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/aspect-aspectJArgs.xml"); Thinker thinker = (Thinker) ctx.getBean("volunteer"); thinker.thinkOfSomething("I'm stupid."); }catch (Exception e){ e.printStackTrace(); } } }
運行結果

總結
上述列出配置文件和注解兩種方式都能實現切面編程。但對於自身業務開發,個人覺得注解方式較好,因為在修改某一切面類時不需要多處修改;
本文描述可能有不對或不全之處,歡迎大家吐槽!
不要讓懶惰占據你的大腦,不要讓妥協拖垮你的人生。青春就是一張票,能不能趕上時代的快車,你的步伐掌握在你的腳下。
