1. 程式人生 > >Spring AOP之全自動方式(AspectJ)

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是自定義字首,後接namespaceURI

    xml檔案中的實現方式


<!--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(){}