1. 程式人生 > >Spring入門學習(AOP) 第十四節

Spring入門學習(AOP) 第十四節

Spring入門學習(AOP)

為什麼需要AOP

  1. 新建一個介面ArithmeticCalculator.java和它的實現類ArithmeticCalculatorImpl
    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); } public class ArithmeticCalculatorImpl 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; } }
    在上述類中,當我們需要為這些類新增日誌時,需要在相應的業務邏輯中取新增,要修改時,可能也會涉及許多改動的地方。
    在這裡插入圖片描述

一種方法是使用動態代理解決

在這裡插入圖片描述

  1. 新建一個代理類ArithmeticCalculatorLoggingProxy
    使用反射可以在方法執行前後做一些事,比如獲取方法名新增日誌處理,最後返回代理類。
    	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: 呼叫方法時,傳入的引數
    			 */
    			@Override
    			public Object invoke(Object proxy, Method method, Object[] args)
    					throws Throwable {
    				
    				// 一般在內部是不會使用proxy物件(自己呼叫自己了)
    				// System.out.println(proxy.toString());
    				
    				String methodName = method.getName();
    				// 日誌
    				System.out.println("the Methdo:"+methodName+"Begins with: "+Arrays.asList(args));
    				// 執行方法
    				Object result = method.invoke(target, args);
    				System.out.println("The method "+methodName+"ends with "+result);
    				return result;
    			}
    		};
    		proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
    		
    		return proxy;
    	}
    }
    
  2. 我們註釋ArithmeticCalculatorImpl類方法中列印的資訊,建立測試方法,使用代理類新增日誌資訊:
    	public class Main {
    
    	public static void main(String[] args) {
    
    		ArithmeticCalculator target = new ArithmeticCalculatorImpl();
    		ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
    		
    		int result = proxy.add(2, 1);
    		System.out.println("-->" + result);
    		
    		result = proxy.div(4, 2);
    		System.out.println("-->" + result);
    	}
    }
    
    測試結果:
    the Methdo:addBegins with: [2, 1]
    The method addends with 3
    -->3
    the Methdo:divBegins with: [4, 2]
    The method divends with 2
    -->2
    

使用Spring AOP

AOP簡介

在這裡插入圖片描述

AOP術語

在這裡插入圖片描述
可以使用@AspectJ註解宣告切面
在這裡插入圖片描述