一入愧,理解AOP(Aspect-oriented Programming)
- 傳統(tǒng)的OOP面向?qū)ο缶幊躺媸蓿肓死^承叫胖,封裝草冈,多態(tài)等概念用來建立對象間的縱向的層次關(guān)系。并不適合定義橫向的關(guān)系瓮增,例如日志代碼怎棱,它分布在所有對象層次中,但是與核心業(yè)務(wù)卻毫無關(guān)系绷跑,這些散布在各處且和核心業(yè)務(wù)無關(guān)的代碼拳恋,導(dǎo)致了大量代碼的重復(fù);
- AOP面向切面編程砸捏,它的關(guān)注點就是如何封裝這些被大量使用谬运,卻和核心業(yè)務(wù)無關(guān)的代碼稱一個個模塊,這些模塊即是切面垦藏;AOP把軟件系統(tǒng)分為兩個部分:核心關(guān)注點(核心業(yè)務(wù))和橫切關(guān)注點(切面)梆暖;
二,理解Spring AOP的一些關(guān)鍵詞:
- 切面:封裝起來的會被大量復(fù)用掂骏,且和核心業(yè)務(wù)無關(guān)的代碼式廷,通常是一些普通的java類;
- 通知:定義了如何去使用這些切面芭挽,通常分為:前置滑废,后置,環(huán)繞袜爪,和異常通知蠕趁;
- 目標(biāo)對象:將會應(yīng)用到通知并被代理的對象;
- 代理對象:目標(biāo)對象織入切面后創(chuàng)建的對象辛馆;
- 切入點:定義對象中的哪些方法將會被攔截并執(zhí)行切面的代碼俺陋;
- 織入:將切面應(yīng)用到目標(biāo)對象并產(chǎn)生代理對象的過程豁延;
三,Spring如何實現(xiàn)AOP
- 基于ProxyFactoryBean的AOP實現(xiàn):
這里分別提供四種不同的通知接口:MethodBeforeAdvice(前置通知),MethodAfterAdvice(后置通知),ThrowsAdvice(異常通知),MethodInterceptor(環(huán)繞通知),設(shè)計普通的java類實現(xiàn)接口中的方法腊状,即可編寫切面代碼即可诱咏;然后重新配置一個代理類的bean,將切面織入目標(biāo)對象缴挖,使用這個代理對象即可袋狞;這個方法過于麻煩,就不列出來了映屋; - 基于Schema的AOP實現(xiàn):
2.1, 定義切面的實現(xiàn)類:
public class AllAdvice
{
public void myBeforeAdvice(JoinPoint joinPoint)
{
System.out.println("前置通知......");
}
public void myAfterAdvice(JoinPoint joinPoint)
{
System.out.println("后置通知......");
}
public void myThrowingAdvice(JoinPoint joinPoint,Exception e)
{
System.out.println("異常通知......");
}
public void myAroundAdvice(ProceedingJoinPoint joinPoint)
{
System.out.println("環(huán)繞通知......");
}
}
??????2.2, 在配置文件設(shè)置AOP:
//裝配AllAdvice的實例
<bean id="allAdvice" class="com.spring.advice.AllAdvice"/>
//進(jìn)行AOP的配置
<aop:config>
<!-- 定義切面 -->
<aop:aspect id="allAdvice" ref="allAdvice">
<!-- 定義切入點苟鸯,切入點采用正則表達(dá)式-->
<aop:pointcut id="show" expression="execution(* com.spring.beans.*(..))" />
<!--給切入點織入切面-->
<!-- 指定前置通知 -->
<aop:before method="myBeforeAdvice" pointcut-ref="show"/>
<!-- 指定后置通知 -->
<aop:after-returning method="myAfterAdvice" pointcut-ref="show" throwing="e"/>
<!-- 指定異常通知 -->
<aop:after-throwing method="myThrowAdvice" pointcut-ref="show"/>
<!-- 指定環(huán)繞通知 -->
<aop:around method="myAroundAdvice" pointcut-ref="show"/>
</aop:aspect>
</aop:config>
- 基于@AspectJ注解的AOP實現(xiàn):
//定義切面
@Aspect
public class AllAdviceByAspectJ
{
//定義切入點
@Pointcut("execution(void com.spring.beans.HelloWorld.show(String))")
//定義切入點名字
private void show(){}
@Pointcut("execution(void com.spring.beans.HelloWorld.log(String))")
private void log(){}
//前置通知
@Before("show(),log()")
public void myBeforeAdvice(JoinPoint joinPoint)
{
System.out.println("calling Schema BeforeAdvice......");
System.out.println(System.currentTimeMillis());
}
//后置通知
@AfterReturning("show()")
public void myAfterAdvice(JoinPoint joinPoint)
{
System.out.println("calling Schema AfterAdvice......");
System.out.println(System.currentTimeMillis());
}
//異常通知
@AfterThrowing(pointcut="show()",throwing="e")
public void myThrowsAdvice(JoinPoint joinPoint,Exception e)
{
System.out.println("calling Schema ThrowsAdvice......"+e.getMessage());
System.out.println(System.currentTimeMillis());
}
//環(huán)繞通知
@Around("show()")
public void myInterceptorAdvice(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("calling Schema InterceptorAdvice......");
System.out.println(System.currentTimeMillis());
joinPoint.proceed();
}
}