Spring AOP之全自動方式(AspectJ)
- 導包
spring-aspects-3.2.0.RELEASE.jar
com.springsourse.org.aspectj.weaver-1.6.8.RELEASE.jar 引入AspectJ的配置
xmlns:aop=”http://www.springframework.org/schema/aop”
值得一提的是xmlns是xml namespaces的縮寫,xsi是自定義字首,後接namespaceURIxml檔案中的實現方式
<!--Aspectj實現-->
<aop:config>
<!--表示切入點-->
<aop:pointcut id="mypointcut"
expression="public boolean com.bamzhy.service.impl.AccountService.transferMoney(*)"/>
<!--advice-ref表示如何增強,pointcut-ref表示增強誰-->
advice-ref="myadvice"
pointcut-ref="mypointcut">
</aop:config>
注意點:不需要通過id獲取代理類了(getBean(“class”)),直接在執行被增強的方法時執行增強。
AspectJ是什麼?
- 基於java的AOP框架
- Spring2.0以後支援了基於AspectJ的切入點表示式的支援
- AspectJ擴充套件了Java語言,提供了一個專門的編譯器,在編譯時提供橫向程式碼的織入。
- 允許直接在POJO(普通Bean)裡邊定義切面類
- 主要用途:不改動現有程式碼的前提下,自定義開發、植入程式碼。
切入點表示式
- 語法:execution(修飾符 返回值 (包.類.方法名(引數型別) )throws 異常)
- 修飾符:一般省略,可以寫public,* 表示任意
- 返回值:void、String、* 表示任意
- 包:> 可以省略,可以使用* 通配(一個*表示一層包)
- 類:可以省略,可以使用* 通配
如果省略的話會降低效率 - throws可以省略
- AspectJ通知型別:
Before:在切入點之前執行。引數型別的校驗(前置通知)
AfterReturning:在切入點之後執行(後置通知),可以對結果進行檢查,增加log
Around:環繞通知在切入點之前和之後都會執行,例如增加事務等
AfterThrowing:丟擲異常的時候執行通知,正常情況下走不到,只有發生異常的情況下才會去通知,記錄一些日誌。
After:在finally語句裡。不管切入點是否有異常發生都會執行。
xml配置:
<!--這裡寫的是所有增強程式碼的實現類-->
<bean id="myadvice" class="com.bamzhy.advice.MyPOJOAdvice"/>
<aop:config>
<!--這裡注入實現類-->
<aop:aspect ref="myadvice">
<aop:pointcut
<!--等待被增強的物件-->
id="mypointcut"
expression="execution (public void com.bamzhy.service.impl.AccountServiceimpl.transferMoney())"/>
<!--增強程式碼1-->
<aop:before method="before" pointcut-ref="mypointcut"/>
<!--增強程式碼2-->
<aop:around method="around" pointcut-ref="mypointcut"/>
<!--增強程式碼3-->
<aop:after-throwing method="afterThrowing" pointcut-ref="mypointcut" throwing="throwable"/>
<!--增強程式碼4-->
<aop:after-returning method="afterReturning" pointcut-ref="mypointcut"/>
<!--增強程式碼5-->
<aop:after method="finallyMethod" pointcut-ref="mypointcut"/>
</aop:aspect>
</aop:config>
MyPOJOAdvice.java中的方法
package com.bamzhy.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyPOJOAdvice {
public void before(){
System.out.println("before");
}
public void afterReturning(){
System.out.println("after-returnig");
}
//這個方法跟動態代理那裡invoke方法很像
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("beforearound");
Object proceed = joinPoint.proceed();
System.out.println("afteraround");
return proceed;
}
public void afterThrowing (JoinPoint j, Throwable throwable){
System.out.println("error" + throwable.getMessage());
}
public void finallyMethod(){
System.out.println("finallyMethod");
}
}
註解方式配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<!--增加context-->
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--掃描下包-->
<context:component-scan base-package="com.bamzhy"/>
<aop:aspectj-autoproxy />
</beans>
使用註解完成配置
增強註解的掃描< context:component-scan base-package=”com.bamzhy” >< /context:component-scan>
< aop:aspectj-autoproxy />
1、@Controller web層
2、@Service 服務 service層
3、@Repository dao層
4、@Component取代< bean class=” ” > @Component(“id”) 取代< bean id=” ” >
5、@Value(” “)給普通欄位注入值
6、@Autowired 通過其使用來消除 set ,get方法。首先在容器中查詢對應型別的bean
,如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的資料,如果查詢的結果不止一個,那麼@Autowired會根據名稱來查詢。
7、@PostConstruct @PreDestory 取代 init-method=”init” destory-method=”destory”
8、@Resource(name=”myaddress”) @Component(“myaddress”)
(等價於< property name=”address” ref=”myaddress” >)
@Aspect 宣告切面,修飾切面類,從而獲得增強
Advice中的:
@Before(“myPointCut”)前置
@AfterReturning(“myPointCut”) 後置
@Around(“myPointCut”)環繞
@AfterThrowing(pointcut = “myPointCut()”,throwing = “throwable”)丟擲異常
@After(“myPointCut”)最終
切入點:
@PointCut(裡邊寫要增強的方法的全類名+方法名) 自己在Advice類裡邊定義一個方法
private void myPointCut(){}