AOP全名Aspect-Oriented Programming,中文直譯爲面向切面(方面)編程。何爲切面,就好比說咱們系統中的權限管理,日誌,事務等咱們均可以將其當作一個個切面。html
Spring AOP 採用的是動態代理的設計模式來實現切面編程的。spring
首先,咱們能夠經過 express
23種設計模式----------代理模式(三) 之 動態代理模式編程
來了解下動態代理模式,再次再也不贅述。設計模式
咱們來看看Spring AOP 是怎樣運用動態代理模式的。在Spring AOP 經過安全
<aop:aspect id="fourAdviceAspect" ref="fourAdviceBean" order="2">
<aop:aspect ref="advices"> <!--切點--> <aop:pointcut id="pointcut1" expression="execution(* com.jay.springAOP.aop01.Math.*(..))"/> <!--鏈接通知方法與切點--> <aop:before method="before" pointcut-ref="pointcut1"/> <aop:after method="after" pointcut-ref="pointcut1"/> </aop:aspect>
<aop:pointcut id="myPointcut" expression="execution(* com.wicresoft.app.service.impl.*.*(..))" method="release" />
通知類型app
try{
//前置通知
//環繞通知
//調用目標對象方法
//環繞通知
//後置通知
}catch(){
//異常通知
}finally{
//終止通知
}模塊化
注:圖片來源於:http://blog.csdn.net/lirui0822/article/details/8555691 post
關於PointCut中使用的execution的說明:性能
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:方法的操做權限
ret-type-pattern:返回值
declaring-type-pattern:方法所在的包
name-pattern:方法名
parm-pattern:參數名
throws-pattern:異常
記憶法則就是Java定義一個方法時的樣子:public boolean produceValue(int oo) throws Exception, 只要在方法名前加上包名就能夠了。
其中,除ret-type-pattern和name-pattern以外,其餘都是可選的。上例中,execution(* com.spring.service.*.*(..))表示com.spring.service包下,返回值爲任意類型;方法名任意;參數不做限制的全部方法。
一、首先定義一個日誌切面,採用前置通知
package com.jay.springAOP.aopDecorator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 一個用於記錄日誌的切面
* Created by xiang.wei on 2017/8/14.
*/
@Component
@Aspect
public class LoggerAdvices {
@Before("execution(* com.jay.springAOP.aopDecorator.*.*(..))")
public void addLogger(JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName());
Logger logger= LoggerFactory.getLogger(this.getClass());
//記錄日誌
logger.debug("-------起始操做----------");
logger.debug("-------結束操做-----------");
}
}
二、定義一個用於性能統計的切面,其中定義了一個環繞通知
package com.jay.springAOP.aopDecorator; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; /** * 一個用於性能的統計 * Created by xiang.wei on 2017/8/14. */ @Component @Aspect public class PerformanceAdvices { @Around("execution(* com.jay.springAOP.aopDecorator.*.*(..))") public Object execute(ProceedingJoinPoint pjp) throws Throwable { System.out.println(pjp.getSignature().getName()); System.out.println("開始時間:"+System.currentTimeMillis()); Object result = pjp.proceed(); System.out.println("結束時間:"+System.currentTimeMillis()); return result; } }
三、相關的業務代碼
package com.jay.springAOP.aopDecorator; import org.springframework.stereotype.Service; /** * Created by xiang.wei on 2017/8/14. */ @Service("paymentCommand") public class PaymentCommand { public void pay() { //執行下訂單操做 int j=0; for (int i=0;i<10000;i++ ) { j++; } //執行支付操做 System.out.println("進行支付"); } }
package com.jay.springAOP.aopDecorator; import org.springframework.stereotype.Service; /** * Created by xiang.wei on 2017/8/14. */ @Service("placeOrderCommand") public class PlaceOrderCommand{ public void handleOrder() { //執行下訂單操做 int j=0; for (int i=0;i<100000;i++ ) { j++; } System.out.println("進行下單操做"); } }
四、測試類:
package com.jay.springAOP.aopDecorator; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by xiang.wei on 2017/8/15. */ public class Client { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("aopDecorator.xml"); PlaceOrderCommand placeOrderCommand = ctx.getBean("placeOrderCommand", PlaceOrderCommand.class); placeOrderCommand.handleOrder(); PaymentCommand paymentCommand = ctx.getBean("paymentCommand",PaymentCommand.class); paymentCommand.pay(); } }
測試結果以下: