歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Spring AOP的實現原理

Spring AOP的實現原理

日期:2017/3/1 9:17:25   编辑:Linux編程

簡介

前段時間寫的java設計模式--代理模式,最近在看Spring Aop的時候,覺得於代理模式應該有密切的聯系,於是決定了解下Spring Aop的實現原理。

說起AOP就不得不說下OOP了,OOP中引入封裝、繼承和多態性等概念來建立一種對象層次結構,用以模擬公共行為的一個集合。但是,如果我們需要為部分對象引入公共部分的時候,OOP就會引入大量重復的代碼。例如:日志功能。

AOP技術利用一種稱為“橫切”的技術,解剖封裝的對象內部,並將那些影響了多個類的公共行為封裝到一個可重用模塊,這樣就能減少系統的重復代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。AOP把軟件系統分為兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關系不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在核心關注點的多處,而各處都基本相似。比如權限認證、日志、事務處理。

實現原理

前面在學習代理模式的時候,了解到代理模式分為動態代理和靜態代理。現在我們就以代理模式為基礎先實現我們自己的AOP框架,再來研究Spring的AOP的實現原理。

先以靜態代理實現,靜態代理關鍵是在代理對象和目標對象實現共同的接口,並且代理對象持有目標對象的引用。

Spring AOP自定義注解方式實現日志管理 http://www.linuxidc.com/Linux/2015-11/125019.htm

Spring AOP進行日志記錄 http://www.linuxidc.com/Linux/2015-11/124731.htm

使用Spring AOP進行性能監控 http://www.linuxidc.com/Linux/2012-07/64681.htm

利用Spring AOP 更新Memcached 緩存策略的實現 http://www.linuxidc.com/Linux/2012-03/56503.htm

Spring AOP的兩種代理 http://www.linuxidc.com/Linux/2015-11/125017.htm

Spring AOP的注解實例 http://www.linuxidc.com/Linux/2015-11/125018.htm

公共接口代碼:

public interface IHello {
/**
* 業務方法
* @param str
*/
void sayHello(String str);
}

目標類代碼:

public class Hello implements IHello{
@Override
public void sayHello(String str) {
System.out.println("hello "+str);
}

}

代理類代碼,我們給它添加日志記錄功能,在方法開始前後執行特定的方法,是不是和AOP特別像呢?

public class ProxyHello implements IHello{
private IHello hello;
public ProxyHello(IHello hello) {
super();
this.hello = hello;
}
@Override
public void sayHello(String str) {
Logger.start();//添加特定的方法
hello.sayHello(str);
Logger.end();
}

}

日志類代碼:

public class Logger {
public static void start(){
System.out.println(new Date()+ " say hello start...");
}

public static void end(){
System.out.println(new Date()+ " say hello end");
}
}

測試代碼:

public class Test {
public static void main(String[] args) {
IHello hello = new ProxyHello(new Hello());//如果我們需要日志功能,則使用代理類
//IHello hello = new Hello();//如果我們不需要日志功能則使用目標類
hello.sayHello("明天");
}
}

這樣我們就實現了一個最簡單的AOP,但是這樣會存在一個問題:如果我們像Hello這樣的類很多,那麼,我們是不是要去寫很多個HelloProxy這樣的類呢。其實也是一種很麻煩的事。在jdk1.3以後,jdk跟我們提供了一個API java.lang.reflect.InvocationHandler的類, 這個類可以讓我們在JVM調用某個類的方法時動態的為些方法做些什麼事。下面我們就來實現動態代理的實現。

動態代理實現主要是實現InvocationHandler,並且將目標對象注入到代理對象中,利用反射機制來執行目標對象的方法。

接口實現與靜態代理相同,代理類代碼:

public class DynaProxyHello implements InvocationHandler{

private Object target;//目標對象
/**
* 通過反射來實例化目標對象
* @param object
* @return
*/
public Object bind(Object object){
this.target = object;
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Logger.start();//添加額外的方法
//通過反射機制來運行目標對象的方法
result = method.invoke(this.target, args);
Logger.end();
return result;
}

}

測試類代碼:

public class DynaTest {
public static void main(String[] args) {
IHello hello = (IHello) new DynaProxyHello().bind(new Hello());//如果我們需要日志功能,則使用代理類
//IHello hello = new Hello();//如果我們不需要日志功能則使用目標類
hello.sayHello("明天");
}
}

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2016-04/129717p2.htm

Copyright © Linux教程網 All Rights Reserved