javascript
Spring 学习二-----AOP的原理与简单实践
一、Spring ?AOP的原理
AOP全名Aspect-Oriented Programming,中文直譯為面向切面(方面)編程。何為切面,就比如說我們系統(tǒng)中的權(quán)限管理,日志,事務(wù)等我們都可以將其看成一個個切面。
Spring AOP 采用的是動態(tài)代理的設(shè)計模式來實現(xiàn)切面編程的。
首先,我們可以通過?
23種設(shè)計模式----------代理模式(三) 之 動態(tài)代理模式
來了解下動態(tài)代理模式,再次不再贅述。
我們來看看Spring AOP 是怎樣運用動態(tài)代理模式的。在Spring AOP 通過
調(diào)用流程如下: 1、實現(xiàn)InvocationHandler接口 2、通過ProxyFactoryBean用于創(chuàng)建代理類(根據(jù)Advisor生成的Bean,也就是TargetBean的代理) 3、調(diào)用invoke方法? 然后,AOP中幾個重要的概念是: 1、關(guān)注點(concern)?? 一個關(guān)注點可以是一個特定的問題,概念、或者應(yīng)用程序的興趣點。總而言之,應(yīng)用程序必須達(dá)到一個目標(biāo)
?? 安全驗證、日志記錄、事務(wù)管理都是一個關(guān)注點
?? 在oo應(yīng)用程序中,關(guān)注點可能已經(jīng)被代碼模塊化了還可能散落在整個對象模型中
2、橫切關(guān)注點(crosscutting concern)
?? 如何一個關(guān)注點的實現(xiàn)代碼散落在多個類中或方法中
3、方面(aspect)
?? 一個方面是對一個橫切關(guān)注點模塊化,它將那些原本散落在各處的,
?? 用于實現(xiàn)這個關(guān)注點的代碼規(guī)整在一處,可以通過@Aspect標(biāo)注或在applictionContext.xml中進(jìn)行配置:? <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean" order="2"> 4、建議(advice)通知
?? advice是point cut執(zhí)行代碼,是方面執(zhí)行的具體實現(xiàn),如 <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> 5、切入點(pointcut)
?? 用于指定某個建議用到何處 <aop:pointcut id="myPointcut" expression="execution(* com.wicresoft.app.service.impl.*.*(..))" method="release" /> 6、織入(weaving)
?? 將aspect(方面)運用到目標(biāo)對象的過程
7、連接點(join point)
? 程序執(zhí)行過程中的一個點?
?通知類型
try{
//前置通知
//環(huán)繞通知
//調(diào)用目標(biāo)對象方法
//環(huán)繞通知
//后置通知
}catch(){
//異常通知
}finally{
//終止通知
}
?
?
注:圖片來源于:http://blog.csdn.net/lirui0822/article/details/8555691?
關(guān)于PointCut中使用的execution的說明:
execution(modifiers-pattern??ret-type-pattern?declaring-type-pattern??name-pattern(param-pattern)?throws-pattern?)?
modifiers-pattern:方法的操作權(quán)限
ret-type-pattern:返回值
declaring-type-pattern:方法所在的包
name-pattern:方法名
parm-pattern:參數(shù)名
throws-pattern:異常
記憶法則就是Java定義一個方法時的樣子:public boolean produceValue(int oo) throws Exception, 只要在方法名前加上包名就可以了。
其中,除ret-type-pattern和name-pattern之外,其他都是可選的。上例中,execution(* com.spring.service.*.*(..))表示com.spring.service包下,返回值為任意類型;方法名任意;參數(shù)不作限制的所有方法。
二、Spring AOP的簡單實踐
1、首先定義一個日志切面,采用前置通知
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("-------結(jié)束操作-----------");
}
}
2、定義一個用于性能統(tǒng)計的切面,其中定義了一個環(huán)繞通知
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;/*** 一個用于性能的統(tǒng)計* 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("結(jié)束時間:"+System.currentTimeMillis());return result;} }3、相關(guān)的業(yè)務(wù)代碼
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() {//執(zhí)行下訂單操作int j=0;for (int i=0;i<10000;i++ ) {j++;}//執(zhí)行支付操作System.out.println("進(jìn)行支付");} } 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() {//執(zhí)行下訂單操作int j=0;for (int i=0;i<100000;i++ ) {j++;}System.out.println("進(jìn)行下單操作");} }4、測試類:
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();} }測試結(jié)果如下:
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/Fly-Bob/p/7368129.html
總結(jié)
以上是生活随笔為你收集整理的Spring 学习二-----AOP的原理与简单实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jquer 的简输出
- 下一篇: Spring事务源码分析