1. 程式人生 > >spring_(15) AOP 相關基礎之一(動態代理解決問題)

spring_(15) AOP 相關基礎之一(動態代理解決問題)

IOC和AOP是Spring的兩大基石。

AOP前奏

在這裡插入圖片描述

程式碼實現片段

在這裡插入圖片描述

問題

  • 程式碼混亂:越來越多的非業務需求(日誌和驗證等)加入後,原有的業務方法急劇膨脹。每個方法在處理核心邏輯的同時還必須兼顧其他多個關注點
  • 程式碼分散:以日誌需求為例,只是為了滿足這個單一需求,就不得不在多個模組(方法)裡多次重複相同的日誌程式碼。如果日誌需求發生變化,必須修改所有模組

使用動態代理解決上述問題(開發不建議使用,對程式設計師要求較高,推薦AOP解決這個問題)

  • 代理設計模式的原理:使用一個代理將物件包裝起來,然後用該代理物件取代原始物件。任何對原始物件的呼叫都要通過代理。代理物件決定是否以及何時將方法呼叫轉到原始物件上。

在這裡插入圖片描述

例子程式

基本結構

在這裡插入圖片描述

ArithmeticCalculator.java

package com.spring.aop.helloworld;
public interface ArithmeticCalculator {
    int add(int i,int j);
    int sub(int i,int j);
    int mul(int i,int j);
    int div(int i,int j);
}

ArithmeticCaluculatorImpl.java

package com.spring.aop.helloworld;
public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { int result = i+j; return result; } @Override public int sub(int i, int j) { int result = i-j; return result; } @Override public
int mul(int i, int j) { int result = i*j; return result; } @Override public int div(int i, int j) { int result = i/j; return result; } }

ArithmeticCalculatorLoggingImpl.java

package com.spring.aop.helloworld;

public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {

    @Override
    public int add(int i, int j) {
        System.out.println("The method add begins with["+i+","+j+"]");
        int result = i+j;
        System.out.println("The method add ends with"+result);
        return result;
    }

    @Override
    public int sub(int i, int j) {
        System.out.println("The method sub begins with["+i+","+j+"]");
        int result = i-j;
        System.out.println("The method sub ends with"+result);
        return result;
    }

    @Override
    public int mul(int i, int j) {
        System.out.println("The method mul begins with["+i+","+j+"]");
        int result = i*j;
        System.out.println("The method mul ends with"+result);
        return result;
    }

    @Override
    public int div(int i, int j) {
        System.out.println("The method div begins with["+i+","+j+"]");
        int result = i/j;
        System.out.println("The method div ends with"+result);
        return result;
    }
}

ArithmeticCalculatorLoggingProxy.java

package com.spring.aop.helloworld;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class ArithmeticCalculatorLoggingProxy {

    //要代理的物件
    private ArithmeticCalculator target;

    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target){
        this.target = target;
    }

    public ArithmeticCalculator getLoggingProxy(){
            ArithmeticCalculator proxy = null;

            //代理物件由哪一個類載入器負責載入
            ClassLoader loader = target.getClass().getClassLoader();
            //代理物件的型別,即其中有哪些方法
            Class [] interfaces = new Class[]{ArithmeticCalculator.class};
            //當呼叫代理物件其中的方法時,該執行的程式碼
            InvocationHandler h = new InvocationHandler() {
                /**
                 * proxy:正在返回的那個代理物件,一般情況下,在invoke方法中都不使用該物件。
                 * method:正在被呼叫的方法
                 * args:呼叫方法時,傳入的引數
                 * @param proxy
                 * @param method
                 * @param args
                 * @return
                 * @throws Throwable
                 */
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //這裡如果這樣寫會造成死迴圈System.out.println(proxy.toString());
                    String methodName = method.getName();
                    //日誌
                    System.out.println("ATGUIGU->The method "+methodName+" begins with "+ Arrays.asList(args));
                    //執行方法
                    Object result = method.invoke(target,args);
                    //日誌
                    System.out.println("ATGUIGU->The method "+methodName+" ends with "+result);
                    return  result ;
                }
            };
            proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader,interfaces,h);

            return proxy;
    }
}

Main.java

package com.spring.aop.helloworld;

public class Main {

    public static void main(String[] args){

//        ArithmeticCalculator arithmeticCalculator = null;
//        arithmeticCalculator = new ArithmeticCalculatorLoggingImpl();

        ArithmeticCalculator target = new ArithmeticCalculatorImpl();
        ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();


        int result = proxy.add(1,2);
        System.out.println("-->"+result);

        result = proxy .div(4,2);
        System.out.println("-->"+result);
        
    }

}

執行結果

在這裡插入圖片描述