Spring IOC與AOP
使用spring這麼久了,從來沒好好的總結一下這兩個核心的技術,關於這兩個技術的資料數不勝數,自己也看過一些書、查過一些資料,不過可能由於個人水平有限,總是弄的混混惡惡的,因此今天抽空總結一下。
1、IOC
先從IOC說起,我們平常使用物件的時候,一般都是直接使用關鍵字類new一個物件,使用new那麼就表示當前模組已經不知不覺的和new的物件耦合了。而我們通常都是更高層次的抽象模組呼叫底層的實現模組,這樣也就產生了模組依賴於具體的實現,這樣與我們JAVA中提倡的面向介面面向抽象程式設計是相沖突的。例如:我們在進行資料庫操作的時候,總是業務層呼叫DAO層,當然我們的DAO一般都是會採用介面開發,這在一定程度上滿足了鬆耦合,使業務邏輯層不依賴於具體的資料庫DAO層。(但是我們在使用的時候還是會new一個特定資料庫的DAO層,這無形中也與特定的資料庫綁定了)
IOC,就是DAO介面的實現不再是業務邏輯層呼叫工廠類去獲取,而是通過容器(比如spring)來自動的為我們的業務層設定DAO的實現類。這樣整個過程就反過來,以前是我們業務層主動去獲取DAO,而現在是DAO主動被設定到業務邏輯層中來了,這也就是反轉控制的由來。
2、AOP
舉個例子:當一個類中有5個方法,呼叫每個方法之前都要檢查使用者是否具有許可權,我們可以定義一個公共方法A,5個方法中每個方法都呼叫該公共方法A。如果類中有100個方法,每次呼叫固然很麻煩,如果哪天需求變了,不需要呢,一個個去掉嗎,更費勁。
AOP 的底層實際上是由動態代理實現的。AOP 代理其實是由 AOP 框架動態生成的一個代理物件,該物件可作為目標物件使用。AOP 代理物件包含了目標物件的全部方法,同時又添加了特殊的處理方法,如上面說的檢查許可權之類的操作。所以,是在原目標物件上添加了特殊功能。
最最經典的例項===
定義一個介面:
public interface IHello {
void sayHello(String name);
}
寫個類實現IHello介面
public class Hello implements IHello { public void sayHello(String name) { System.out.println("Hello " + name); } }
現在我們要為這個業務方法加上日誌記錄的業務,我們在不改變原始碼的情況下,我們會去怎麼做呢?也許,你會去寫一個類去實現IHello介面,並依賴Hello這個類.程式碼如下:
public class HelloProxy implements IHello {
private IHello hello;
public HelloProxy(IHello hello) {
this.hello = hello;
}
public void sayHello(String name) {
Logger.logging(Level.DEBUGE, "sayHello method start.");
hello.sayHello(name);
Logger.logging(Level.INFO, "sayHello method end!");
}
}
.Logger類和Level列舉程式碼如下:
Logger.java
import java.util.Date;
public class Logger{
public static void logging(Level level, String context) {
if (level.equals(Level.INFO)) {
System.out.println(new Date().toLocaleString() + " " + context);
}
if (level.equals(Level.DEBUGE)) {
System.err.println(new Date() + " " + context);
}
}
}
Level.java
public enum Level {
INFO,DEBUGE;
}
測試:
public class Test {
public static void main(String[] args) {
IHello hello = new HelloProxy(new Hello());
hello.sayHello("Doublej");
}
}
hello物件是被HelloProxy這個所謂的代理態所建立的.這樣,如果我們以後要把日誌記錄的功能去掉.那我們只要把得到hello物件的程式碼改成以下:
public class Test {
public static void main(String[] args) {
IHello hello = new Hello();
hello.sayHello("Doublej");
}
}