spring 05 aop_註解

weixin_34116110發表於2016-10-13
aop程式設計, 註解方式

概念:
Aop程式設計:

  • 關注點程式碼與業務程式碼分離!(jdk/cglib代理)

關注點:

  • 重複執行的程式碼, 也叫關注點程式碼!

切面:

  • 關注點程式碼形成的類,就叫做切面
    springAop程式設計,也叫面向切面程式設計!

Aop: Aspect Object Programming 面向切面程式設計!

舉例,哪些是切面?
事務,許可權控制, 日誌…

切入點表示式
攔截方法,給方法所在的類,生成代理物件!
Spring在初始化容器的時候,會根據切入點表示式的規則,會符合攔截規則的方法所在的類生成代理物件!

使用Aop開發步驟:

  1. 引入aop 相關 jar檔案

(aspectj 在spring之前,面向切面開發的公用元件)
aopalliance.jar 【spring-framework-2.5.6\lib\aopalliance】
aspectjrt.jar 【spring-framework-2.5.6\lib\aspectj】
aspectjweaver.jar 【spring-framework-2.5.6\lib\aspectj】
spring-aop-3.2.5.RELEASE.jar 【Spring3.2原始碼】

  1. 引入aop名稱空間且開啟aop掃描

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

  1. 開啟aop註解

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

  1. 使用Aop相關注解

@Aspect 指定一個類為切面類
(切面類也需要例項化)
(切面類中的方法,也叫做通知)
@Before 前置通知 【在執行目標物件方法之前執行】
@After 後置通知 【在執行目標物件方法之後執行】
@AfterReturning 返回後通知 【在執行目標物件方法結束後執行, 出現異常不執行】
@AfterThrowing 異常通知 【在執行目標物件方法出現異常時候執行】
@Around 環繞通知 【環繞目標方法執行】
@Pointcut 定義一個切入點表示式變數 (後面使用這個切入點表示式的時候,直接引用方法名即可)

Spring生成代理物件的過程?

  1. 建立容器物件的時候, 根據“切入點表示式”攔截的類,生成代理物件;
  2. 如果目標物件有實現介面,使用jdk代理!
  3. 如果目標物件沒有實現介面,使用cglib代理!
  4. 從容器獲取代理後的物件
  5. 執行代理物件的方法,在執行時期,動態植入“切面”類中的“通知”!
案例

beam.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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.xxjqr.spring01.aop_anno"></context:component-scan>
    
    <!-- 開啟aop註解 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>      

@Component("aop") //預設是transactionAop
@Aspect //宣告一個切面類
public class TransactionAop {
    
    // 定義一個切入點表示式變數  (後面使用這個切入點表示式的時候,直接引用方法名即可)
    @Pointcut("execution(* com.xxjqr.spring01.aop_anno.UserDao.*(..))")  
    public void pointcut_() {
        
    }  

    //【前置通知】
    // 在執行業務方法,之前執行
    @Before("pointcut_()")
    public void beginTransaction() {
        System.out.println("[前置通知]  開啟事務..");
    }
    
    //【後置通知】
    // 在執行業務方法,之後執行
    @After("pointcut_()")
    public void commit() {
        System.out.println("[後置通知] 提交事務..");
    }
    
    // 【返回後通知】   在執行目標方法結束後執行, 出現異常不會執行
    @AfterReturning("pointcut_()")
    public void afterReturing(){
        System.out.println("[返回後通知]");
    }
    
    // 【異常通知】   在執行目標方法的時候出現異常執行
    @AfterThrowing("pointcut_()")
    public void afterThrowing(){
        System.out.println("[異常通知]");
    }
    
    // 【環繞通知】 會環繞目標方法執行
    @Around("pointcut_()")
    public void arroud(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("[環繞前:]");
        pjp.proceed();                 // 執行目標方法
        System.out.println("[環繞後:]");
    }
    
}
@Repository
public class UserDao {
    public void save(){
        System.out.println("已經save");
    }
}
public class App {
    private ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml",getClass());

        
    @Test
    public void testUserAction() {
        //建立容器
        UserDao dao = (UserDao) ac.getBean("userDao");
        System.out.println(dao.getClass());
        dao.save();
    }
    
}

相關文章