AOP概念及在Spring中的使用

1、AOP的使用場景

在業務模塊中,存在一種通用的系統性需求,如日誌、事務管理等。
在常規的方法中,會在業務代碼中直接嵌入平臺代碼。但這樣是2種不相關的代碼混雜,不方便管理。
通過AOP就可以實現在不侵入業務代碼的情況下,實現統一的平臺需求。
舉個例子,如一個類有100個方法,都要嵌入日誌代碼嗎?修改了怎麼辦?
AOP是一種編程概念,通過JDK遠程方法也可以實現,spring中更容易了,寫寫配置就好。

2、AOP的術語

  1. 切面:Aspect,交叉的業務邏輯,如日誌、事務管理。也叫對業務代碼增強。
  2. 織入:Weaving,把切面代碼插入主業務代碼過程。
  3. 連接點:JoinPort,可以被織入的方法。指主業務中的方法。
  4. 切入點:PointCut,切面實際織入的方法。不是所有連接點都被織入。
  5. 目標對象:Target,目標對象,要被增強的對象。
  6. 通知:可以指定織入時機,無法指定切入點。每個連接點都會增強。
  7. 顧問:包含通知,可以針對具體連接點。

簡單來說:AOP就是在業務代碼中插入增強代碼。包含2類4個要素

  1. 業務代碼側:目標代碼,目標方法。
  2. 增強代碼側:增強的內容,觸發的時機。

3、用JDK實現AOP:動態代理

public interface IUser {
    public String sayHello(String msg);
    public String goRun();
}

public class UserImpl implements IUser {
    @Override
    public String sayHello(String msg) {
        System.out.println( "你好,"+msg);
        return "";
    }

    public String goRun() {
        System.out.println( "i'm running");
        return "i'm running";
    }
	
	public static void main(String[] args) {
        final IUser target3 = new UserImpl();
       /*a proxy class that is defined in the specified class loader
     *          and that implements the specified interfaces
     * 所以第1、2個參數分別是目標類和目標類實現的接口*/
        IUser proxy3 = (IUser) Proxy.newProxyInstance(target3.getClass().getClassLoader(), target3.getClass().getInterfaces(), new InvocationHandler() {

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            /**代理類裏重構了invoke方法,代理類的方法調用時,是派發到代理類內部的
        目標類上執行的。
        但是,invoke方法裏可以添加切面了*/
                //前置通知
                System.out.println("判斷用戶是否有權限進行操作");
                //目標類方法
                Object obj = method.invoke(target3, args);
                //後置通知
                System.out.println("記錄用戶執行操作的用戶信息、更改內容和時間等");
                return obj;
            }
        });

        Object obj3 = proxy3.sayHello("地球");
    }
}

實現方法:
1.目標類必須實現了接口;
2.用Proxy.newProxyInstance創建代理類
3.代理類包含了目標類實例,重構了invoke方法
4.在代理類的invoke方法中,執行目標類的方法,並可以加入前後通知

4、spring中AOP的實現

增強代碼,已後置通知爲例

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("執行前置通知方法");
    }
}

ApplicationContext.xml配置

    <!--註冊目標對象-->
    <bean id="myUserSerice" class="master3.UserImpl"></bean>

    <!--註冊切面:通知-->
    <bean id="myAdvice" class="master3.MyMethodBeforeAdvice"/>

    <!--註冊代理工廠-->
    <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--指定目標對象,沒有目標方法,因爲是advice,不能指定方法,全部增強了-->
        <property name="target" ref="myUserSerice"> </property>
        <!--指定增強代碼,時機是後置通知,通過繼承設定了-->
        <property name="interceptorNames" value="myAdvice" ></property>

    </bean>

測試代碼:

@Test
    public void test01(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        IUser myUser=(IUser)ac.getBean("serviceProxy");
        myUser.sayHello("地球");
        myUser.goRun();
    }

輸出

執行前置通知方法
你好,地球
執行前置通知方法
i'm running

總結

  1. AOP是一種編程方法
  2. 適用於不修改業務代碼的情況下對其增強
  3. 記住2類4概念:目標代碼,目標方法;增強代碼,觸發時機。
  4. spring裏改改參數文件就能實現
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章