最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入淺析Spring 的aop實(shí)現(xiàn)原理

 更新時(shí)間:2016年03月31日 11:46:24   作者:ngulc  
AOP(Aspect-OrientedProgramming,面向方面編程),可以說(shuō)是OOP(Object-Oriented Programing,面向?qū)ο缶幊蹋┑难a(bǔ)充和完善。本文給大家介紹Spring 的aop實(shí)現(xiàn)原理,感興趣的朋友一起學(xué)習(xí)吧

什么是AOP

AOP(Aspect-OrientedProgramming,面向方面編程),可以說(shuō)是OOP(Object-Oriented Programing,面向?qū)ο缶幊蹋┑难a(bǔ)充和完善。OOP引入封裝、繼承和多態(tài)性等概念來(lái)建立一種對(duì)象層次結(jié)構(gòu),用以模擬公共行為的一個(gè)集合。當(dāng)我們需要為分散的對(duì)象引入公共行為的時(shí)候,OOP則顯得無(wú)能為力。也就是說(shuō),OOP允許你定義從上到下的關(guān)系,但并不適合定義從左到右的關(guān)系。例如日志功能。日志代碼往往水平地散布在所有對(duì)象層次中,而與它所散布到的對(duì)象的核心功能毫無(wú)關(guān)系。對(duì)于其他類(lèi)型的代碼,如安全性、異常處理和透明的持續(xù)性也是如此。這種散布在各處的無(wú)關(guān)的代碼被稱(chēng)為橫切(cross-cutting)代碼,在OOP設(shè)計(jì)中,它導(dǎo)致了大量代碼的重復(fù),而不利于各個(gè)模塊的重用。

簡(jiǎn)介

  前段時(shí)間寫(xiě)的java設(shè)計(jì)模式--代理模式,最近在看Spring Aop的時(shí)候,覺(jué)得于代理模式應(yīng)該有密切的聯(lián)系,于是決定了解下Spring Aop的實(shí)現(xiàn)原理。

  說(shuō)起AOP就不得不說(shuō)下OOP了,OOP中引入封裝、繼承和多態(tài)性等概念來(lái)建立一種對(duì)象層次結(jié)構(gòu),用以模擬公共行為的一個(gè)集合。但是,如果我們需要為部分對(duì)象引入公共部分的時(shí)候,OOP就會(huì)引入大量重復(fù)的代碼。例如:日志功能。

  AOP技術(shù)利用一種稱(chēng)為“橫切”的技術(shù),解剖封裝的對(duì)象內(nèi)部,并將那些影響了多個(gè)類(lèi)的公共行為封裝到一個(gè)可重用模塊,這樣就能減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來(lái)的可操作性和可維護(hù)性。AOP把軟件系統(tǒng)分為兩個(gè)部分:核心關(guān)注點(diǎn)和橫切關(guān)注點(diǎn)。業(yè)務(wù)處理的主要流程是核心關(guān)注點(diǎn),與之關(guān)系不大的部分是橫切關(guān)注點(diǎn)。橫切關(guān)注點(diǎn)的一個(gè)特點(diǎn)是,他們經(jīng)常發(fā)生在核心關(guān)注點(diǎn)的多處,而各處都基本相似。比如權(quán)限認(rèn)證、日志、事務(wù)處理。

實(shí)現(xiàn)原理  

  前面在學(xué)習(xí)代理模式的時(shí)候,了解到代理模式分為動(dòng)態(tài)代理和靜態(tài)代理。現(xiàn)在我們就以代理模式為基礎(chǔ)先實(shí)現(xiàn)我們自己的AOP框架,再來(lái)研究Spring的AOP的實(shí)現(xiàn)原理。

  先以靜態(tài)代理實(shí)現(xiàn),靜態(tài)代理關(guān)鍵是在代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)共同的接口,并且代理對(duì)象持有目標(biāo)對(duì)象的引用。

  公共接口代碼:

public interface IHello {
/**
* 業(yè)務(wù)方法
* @param str
*/
void sayHello(String str);
} 
  目標(biāo)類(lèi)代碼:

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

  代理類(lèi)代碼,我們給它添加日志記錄功能,在方法開(kāi)始前后執(zhí)行特定的方法,是不是和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();
}
}

  日志類(lèi)代碼:

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");
}
}

  測(cè)試代碼:

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

  這樣我們就實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的AOP,但是這樣會(huì)存在一個(gè)問(wèn)題:如果我們像Hello這樣的類(lèi)很多,那么,我們是不是要去寫(xiě)很多個(gè)HelloProxy這樣的類(lèi)呢。其實(shí)也是一種很麻煩的事。在jdk1.3以后,jdk跟我們提供了一個(gè)API java.lang.reflect.InvocationHandler的類(lèi), 這個(gè)類(lèi)可以讓我們?cè)贘VM調(diào)用某個(gè)類(lèi)的方法時(shí)動(dòng)態(tài)的為些方法做些什么事。下面我們就來(lái)實(shí)現(xiàn)動(dòng)態(tài)代理的實(shí)現(xiàn)。

  動(dòng)態(tài)代理實(shí)現(xiàn)主要是實(shí)現(xiàn)InvocationHandler,并且將目標(biāo)對(duì)象注入到代理對(duì)象中,利用反射機(jī)制來(lái)執(zhí)行目標(biāo)對(duì)象的方法。

  接口實(shí)現(xiàn)與靜態(tài)代理相同,代理類(lèi)代碼:

public class DynaProxyHello implements InvocationHandler{
private Object target;//目標(biāo)對(duì)象
/**
* 通過(guò)反射來(lái)實(shí)例化目標(biāo)對(duì)象
* @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();//添加額外的方法
//通過(guò)反射機(jī)制來(lái)運(yùn)行目標(biāo)對(duì)象的方法
result = method.invoke(this.target, args);
Logger.end();
return result;
}
}

  測(cè)試類(lèi)代碼:

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

  看完上面的代碼可能和Spring AOP相比有一個(gè)問(wèn)題,日志類(lèi)只能在方法前后打印,但是AOP應(yīng)該是可以在滿(mǎn)足條件就可以執(zhí)行,所有是否可以將DynaPoxyHello對(duì)象和日志操作對(duì)象(Logger)解耦呢?

  看下面代碼實(shí)現(xiàn),將將DynaPoxyHello對(duì)象和日志操作對(duì)象(Logger)解耦:

  我們要在被代理對(duì)象的方法前面或者后面去加上日志操作代碼(或者是其它操作的代碼),那么,我們可以抽象出一個(gè)接口,這個(gè)接口里就只有兩個(gè)方法:一個(gè)是在被代理對(duì)象要執(zhí)行方法之前執(zhí)行的方法,我們?nèi)∶麨閟tart,第二個(gè)方法就是在被代理對(duì)象執(zhí)行方法之后執(zhí)行的方法,我們?nèi)∶麨閑nd。

  Logger的接口:

public interface ILogger {
void start(Method method);
void end(Method method);
}

  Logger的接口實(shí)現(xiàn):

public class DLogger implements ILogger{
@Override
public void start(Method method) {
System.out.println(new Date()+ method.getName() + " say hello start...");
}
@Override
public void end(Method method) {
System.out.println(new Date()+ method.getName() + " say hello end");
}
}

 動(dòng)態(tài)代理類(lèi):

public class DynaProxyHello implements InvocationHandler{
//調(diào)用對(duì)象
private Object proxy;
//目標(biāo)對(duì)象
private Object target;
public Object bind(Object target,Object proxy){
this.target=target;
this.proxy=proxy;
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;
//反射得到操作者的實(shí)例
Class clazz = this.proxy.getClass();
//反射得到操作者的Start方法
Method start = clazz.getDeclaredMethod("start", new Class[]{Method.class});
//反射執(zhí)行start方法
start.invoke(this.proxy, new Object[]{this.proxy.getClass()});
//執(zhí)行要處理對(duì)象的原本方法
method.invoke(this.target, args);
//反射得到操作者的end方法
Method end = clazz.getDeclaredMethod("end", new Class[]{Method.class});
//反射執(zhí)行end方法
end.invoke(this.proxy, new Object[]{method});
return result;
}
} 

  測(cè)試代碼:

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

  通過(guò)上面例子,可以發(fā)現(xiàn)通過(guò)動(dòng)態(tài)代理和發(fā)射技術(shù),已經(jīng)基本實(shí)現(xiàn)了AOP的功能,如果我們只需要在方法執(zhí)行前打印日志,則可以不實(shí)現(xiàn)end()方法,這樣就可以控制打印的時(shí)機(jī)了。如果我們想讓指定的方法打印日志,我們只需要在invoke()方法中加一個(gè)對(duì)method名字的判斷,method的名字可以寫(xiě)在xml文件中,這樣我們就可以實(shí)現(xiàn)以配置文件進(jìn)行解耦了,這樣我們就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的spring aop框架。

以上內(nèi)容是小編給大家介紹的Spring 的aop實(shí)現(xiàn)原理 ,希望對(duì)大家有所幫助!

相關(guān)文章

  • Spring Boot 之HelloWorld開(kāi)發(fā)案例

    Spring Boot 之HelloWorld開(kāi)發(fā)案例

    這篇文章主要介紹了Spring Boot 之HelloWorld開(kāi)發(fā)案例,需要的朋友可以參考下
    2017-04-04
  • Nacos啟動(dòng)出現(xiàn)failed to req API:/nacos/v1/ns/instance after all servers問(wèn)題

    Nacos啟動(dòng)出現(xiàn)failed to req API:/nacos/v1/ns/insta

    這篇文章主要介紹了Nacos啟動(dòng)出現(xiàn)failed to req API:/nacos/v1/ns/instance after all servers問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 詳解Java數(shù)組的四種拷貝方式

    詳解Java數(shù)組的四種拷貝方式

    Java數(shù)組一共有四種拷貝方式: for循環(huán)、copyof/copyOfRange、arraycopy和clone。本文將為大家詳細(xì)介紹一下這四種方式,感興趣的可以了解一下
    2022-02-02
  • springboot利用AOP完成日志統(tǒng)計(jì)的詳細(xì)步驟

    springboot利用AOP完成日志統(tǒng)計(jì)的詳細(xì)步驟

    項(xiàng)目用到了過(guò)濾器,可能有的人會(huì)不理解,之所以用過(guò)濾器是因?yàn)橄胍谌罩居涗沺ost請(qǐng)求的json數(shù)據(jù)。本文重點(diǎn)給大家介紹springboot利用AOP完成日志統(tǒng)計(jì)的詳細(xì)步驟,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • 詳解Java 中程序內(nèi)存的分析

    詳解Java 中程序內(nèi)存的分析

    這篇文章主要介紹了詳解Java 中程序內(nèi)存的分析的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Springboot3+Vue3實(shí)現(xiàn)JWT登錄鑒權(quán)功能

    Springboot3+Vue3實(shí)現(xiàn)JWT登錄鑒權(quán)功能

    JWT用于在網(wǎng)絡(luò)應(yīng)用間安全的傳遞消息,它以緊湊且自包含的方式,通過(guò)JSON對(duì)象在各方之間傳遞經(jīng)過(guò)驗(yàn)證的信息,這篇文章主要介紹了Springboot3+Vue3實(shí)現(xiàn)JWT登錄鑒權(quán)功能,需要的朋友可以參考下
    2025-03-03
  • springboot操作阿里云OSS實(shí)現(xiàn)文件上傳,下載,刪除功能

    springboot操作阿里云OSS實(shí)現(xiàn)文件上傳,下載,刪除功能

    這篇文章主要介紹了springboot操作阿里云OSS實(shí)現(xiàn)文件上傳,下載,刪除功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Java垃圾回收之標(biāo)記壓縮算法詳解

    Java垃圾回收之標(biāo)記壓縮算法詳解

    今天小編就為大家分享一篇關(guān)于Java垃圾回收之標(biāo)記壓縮算法詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • 詳解java 中的CAS與ABA

    詳解java 中的CAS與ABA

    這篇文章主要介紹了java 中的CAS與ABA的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05
  • Java使用POI將多個(gè)Sheet合并為一個(gè)Sheet

    Java使用POI將多個(gè)Sheet合并為一個(gè)Sheet

    這篇文章主要為大家詳細(xì)介紹了Java使用POI將多個(gè)Sheet合并為一個(gè)Sheet,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04

最新評(píng)論

麻城市| 科尔| 张北县| 遂溪县| 冕宁县| 乐安县| 长汀县| 陈巴尔虎旗| 吴堡县| 龙海市| 项城市| 潮州市| 巫山县| 平昌县| 隆化县| 宁武县| 永清县| 普陀区| 嘉祥县| 卫辉市| 浏阳市| 鹰潭市| 武夷山市| 三亚市| 泽州县| 瓦房店市| 崇文区| 韩城市| 宁波市| 镇安县| 兰西县| 玉田县| 武陟县| 五大连池市| 乐都县| 辽源市| 衡阳县| 深水埗区| 安康市| 铜山县| 丰都县|