OOP(Object Oriented Programming)面向對象編程解決了縱向上的層次分割,例如MVC模式將展現層、持久化層、邏輯處理層一一分開了,使得開發效率獲得了較大提升,可是這只是縱向上的分割,若是從水平方向上來看,即若是一個項目中的不少類都須要實現某一個方法(例如:在網購平臺上,登陸,下單,付款都須要對身份進行驗證)若是要在這些類一一將這些都要執行的方法添加到其中這無疑將會增長代碼量,這會使得程序顯得很臃腫。基於以上的操做便誕生了咱們今天的主角----Spring-AOP。AOP即(Aspect Oriented Programming)面向切面編程。Spring-AOP就是實現一閃剛提出的問題。接下來咱們就爲你們揭開Spring-AOP的「神祕面紗」。spring
1.1 什麼是AOPexpress
AOP(Aspect Oriented Programming)面向切面編程,是對傳統的OOP(ObjectOriented Programming)面向對象編程的補充。
1.2 AOP的做用編程
若是A,B,C三個方法都要在執行前作驗證操做,執行後作日誌打印操做。腫麼辦? ![圖片描述][1]
1.3 AOP專業術語測試
切面(Aspect): A,B,C,方法執行前都要調用的驗證邏輯和執行後都要調用的日誌邏輯,這兩個就是切面。
通知(Advice): 有五種通知,執行前,執行後,執行成功後,執行拋出異常後,環繞通知。就是切面執行的方法。
目標(Target): 被通知的對象,這裏就是A,B,C三個方法。
鏈接點(Joinpoint):鏈接點是一個應用執行過程當中可以插入一個切面的點。
切點(pointcut):每一個類都擁有多個鏈接點,即鏈接點是程序類中客觀存在的事務。AOP 經過切點定位到特定的鏈接點
打個比方:一天,三位俠客(被通知的對象Target)來我府上作客,被大門(切面Aspect)攔住,門前有五個保安(負責通知的Advice),由於其中一位俠客會降龍十八掌(知足被通知的一個條件Joinpoint),其中一位保安告知他:"你能夠進去了"。另外兩個俠客由於武藝超羣(知足被通知的統一標準poincut)也都進去了。代理
下面咱們以一段實例來說解基於XML配置文件和基於註解的方式來講明Spring-AOP的運行機制。
該程序的總體運行機制是:將入一個項目都想執行加、減、乘、除這四個方法,因此咱們將這四個操做封裝在一個類中並將其做爲一個切面,從而提升代碼的複用率。日誌
基於XML的使用code
//這個即是咱們的切面,即許多類要執行的方法
package com.zhangguo.Spring052.aop01;
public class Math {component
//加 public int add(int n1,int n2){ int result=n1+n2; System.out.println(n1+"+"+n2+"="+result); return result; } //減 public int sub(int n1,int n2){ int result=n1-n2; System.out.println(n1+"-"+n2+"="+result); return result; } //乘 public int mut(int n1,int n2){ int result=n1*n2; System.out.println(n1+"X"+n2+"="+result); return result; } //除 public int div(int n1,int n2){ int result=n1/n2; System.out.println(n1+"/"+n2+"="+result); return result; }
}xml
//這個就是通知啦,比如是上面所打比方的那五個門衛,全部類要使用上面的切面首先要通過這個類的「審覈」對象
package com.zhangguo.Spring052.aop01; import org.aspectj.lang.JoinPoint; public class Advices { public void before(JoinPoint jp){ System.out.println("----------前置通知----------"); System.out.println(jp.getSignature().getName()); } public void after(JoinPoint jp){ System.out.println("----------最終通知----------"); } }
//下面咱們列出本實例的核心,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:p="http://www.springframework.org/schema/p" 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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 被代理對象 --> <!-- 此爲在橫向切面被統一抽象出來的方法 --> <bean id="math" class="com.zhangguo.Spring052.aop01.Math"></bean> <!-- 通知 --> <bean id="advices" class="com.zhangguo.Spring052.aop01.Advices"></bean> <!-- aop配置 --> <aop:config proxy-target-class="true"> <!--切面 --> <aop:aspect ref="advices"> <!-- 切點 -->
<aop:pointcut expression="execution( com.zhangguo.Spring052.aop01.Math.(..))"id="pointcut1"/>
<!--鏈接通知方法與切點 --> //當實現了通知中的before方法時執行切面中方法 <aop:before method="before" pointcut-ref="pointcut1"/> //當實現了通知中的after方法時執行切面中方法 <aop:after method="after" pointcut-ref="pointcut1"/> </aop:aspect> </aop:config> </beans> //此爲測試類 package com.zhangguo.Spring052.aop01; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aop01.xml"); Math math = ctx.getBean("math", Math.class); int n1 = 100, n2 = 5; math.add(n1, n2); math.sub(n1, n2); math.mut(n1, n2); math.div(n1, n2); } }
基於註解的使用
package com.zhangguo.Spring052.aop02; import org.springframework.stereotype.Service; //此處使用@Service說明該類爲切面 @Service("math") public class Math{ //加 public int add(int n1,int n2){ int result=n1+n2; System.out.println(n1+"+"+n2+"="+result); return result; } //減 public int sub(int n1,int n2){ int result=n1-n2; System.out.println(n1+"-"+n2+"="+result); return result; } //乘 public int mut(int n1,int n2){ int result=n1*n2; System.out.println(n1+"X"+n2+"="+result); return result; } //除 public int div(int n1,int n2){ int result=n1/n2; System.out.println(n1+"/"+n2+"="+result); return result; } } package com.zhangguo.Spring052.aop02; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class Advices { //此註解能夠將Advices設置爲通知類,即當使用到before方法時,便執行execution方括號中的號碼 @Before("execution(* com.zhangguo.Spring052.aop02.Math.*(..))") public void before(JoinPoint jp){ System.out.println("----------前置通知----------"); System.out.println(jp.getSignature().getName()); } @After("execution(* com.zhangguo.Spring052.aop02.Math.*(..))") public void after(JoinPoint jp){ System.out.println("----------最終通知----------"); } } <?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:p="http://www.springframework.org/schema/p" 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/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"> <context:component-scan base-package="com.zhangguo.Spring052.aop02"> </context:component-scan> <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans> //測試類 package com.zhangguo.Spring052.aop02; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aop02.xml"); Math math = ctx.getBean("math", Math.class); int n1 = 100, n2 = 5; math.add(n1, n2); math.sub(n1, n2); math.mut(n1, n2); math.div(n1, n2); } }
最後附上項目源碼地址:
連接:http://pan.baidu.com/s/1hrQIdvu 密碼:eknb