spring_(15) AOP 相關基礎之一(動態代理解決問題)
阿新 • • 發佈:2018-12-02
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);
}
}