springaop自動代理

一、背景
spring的aop就是切面編程,切面編程的意思,就是橫向對方法進行攔截,加入統一的自定義處理邏輯。比如,統計所有方法的執行次數、統計所有方法的執行時間、在打印所有方法的返回值等等。
切面編程用到的就是jdk的代理,也就是設計模式中的代理模式。代理模式即對目標對象創建一個代理對象,代理對象持有目標對象的引用,因此調用代理對象,就完全可以實現對目標對象的調用,而代理對象是我們自己創建的,因此可以在不侵入到目標對象的情況下,添加自定義邏輯。

二、一些概念
1、通知
在springaop中,通知就是切面任務,即在我們對目標對象進行代理之後,需要做的事情,例如上面所說的統計方法的執行次數、打印日誌等行爲。

2、目標對象
這個是我們要進行切面攔截的對象,我們要對某種場景進行攔截,必須要有一個對象。有時候我們甚至不關注目標對象具體要完成的任務,例如,在統計目標對象執行的時間,我們只關注方法執行的時間就行了。

3、切點
切點標註了什麼地方進行切面任務,可以是一個bean,可以是一個方法,支持正則表達式,例如以process結尾的方法等。

4、PointcutAdvisor
該對象用於將通知和切點綁定。當我們分別定義了切點和通知後,spring還不知道切點和通知的關係,因此需要一個綁定

5、自動代理
上面講了一大堆概念,最重要的還是爲目標對象產生一個自動代理,也就是我在調用目標對象的時候,如何才能執行通知。spring提供了一種非常好的自動代理的功能,可以根據PointcutAdvisor直接爲目標對象生成一個代理對象,在bean factory中該bean id存放的就是該代理對象,當我們通過Cal cal = (Cal)appCtx.getBean(“computer”);
方法取出的就是代理對象。

三、代碼
首先,我們要創建一個接口和實現,因爲spring的jdk代理需要接口,實現當然需要,就是具體的目標對象的類。
然後就是創建一個通知,就是代理目標對象後,需要做什麼
最後,最重要的,就是在xml中創建通知、目標對象的bean以及關聯關係。

1、xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       ">
    <!-- 目標類 -->
    <bean id = "computer" class="springaop.Computer">
    </bean>

    <!-- 通知,即代理後要做什麼 -->
    <bean id = "interceptor" class="springaop.Interceptor">
    </bean>

    <!-- 綁定通知和攔截點 -->
    <bean id="sleepAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice" ref="interceptor"/>
    <property name="pattern" value=".*calculate"/>
    </bean>

    <!-- 生成自動代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

</beans>

2、接口

package springaop;

public interface Cal {
    public void calculate(String data);
}

3、目標實現類

package springaop;

public class Computer implements Cal{

    @Override
    public void calculate(String data) {
        System.out.println("i am computer data="+data);
    }

}

4、通知

package springaop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class Interceptor  implements MethodBeforeAdvice,AfterReturningAdvice{

    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {
        System.out.println("before... method="+method.getName()+" args="+args);

    }

    @Override
    public void afterReturning(Object returnValue, Method method,
            Object[] args, Object target) throws Throwable {
        System.out.println("after...");

    }

}

5、測試方法

package springaop;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AutoSpringAopTest {
    @Test
    public void testAOP(){
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("autospringaop.xml");
        Cal cal = (Cal)appCtx.getBean("computer");
        cal.calculate("jianghuiwen");
    }
}

四、輸出及總結
這裏寫圖片描述

整個spring aop的核心思想,就是代理,具體說,就是爲spring容器中的bean,創建一個代理proxy,該代理proxy持有bean的引用,該代理proxy還綁定了一些自定義的邏輯,在調用該bean的方法的時候,就會執行proxy的業務邏輯。

五、應用遐想
springaop能幹什麼?很多很多,只要你能想得到。
例如,對某些指定的方法打印日誌、計算指定方法的執行時間、計算方法的執行鏈路、緩存、方法修飾、打印參數、遠程調用、異常統一處理、調用統計、指定方法的返回值統計

發佈了344 篇原創文章 · 獲贊 25 · 訪問量 52萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章