spring aop原理:1、AOP 面向切面,是一種編程范式,提供從另一個(gè)角度來(lái)考慮程序結(jié)構(gòu)以完善面向?qū)ο缶幊蘋(píng)OP;2、AOP為開(kāi)發(fā)者提供了一種描述橫切關(guān)注點(diǎn)的機(jī)制,并能夠自動(dòng)將橫切關(guān)注點(diǎn)織入到面向?qū)ο蟮能浖到y(tǒng)中。
spring aop原理:
AOP(面向切面)是一種編程范式,提供從另一個(gè)角度來(lái)考慮程序結(jié)構(gòu)以完善面向?qū)ο缶幊蹋∣OP)。
AOP為開(kāi)發(fā)者提供了一種描述橫切關(guān)注點(diǎn)的機(jī)制,并能夠自動(dòng)將橫切關(guān)注點(diǎn)織入到面向?qū)ο蟮能浖到y(tǒng)中,從而實(shí)現(xiàn)了橫切關(guān)注點(diǎn)的模塊化。
AOP能夠?qū)⒛切┡c業(yè)務(wù)無(wú)關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任,例如事務(wù)處理、日志管理、權(quán)限控制等,封裝起來(lái),便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來(lái)的可操作性和可維護(hù)性。
使用AOP的好處
降低模塊的耦合度
使系統(tǒng)容易擴(kuò)展
提高代碼復(fù)用性
AOP的基本概念
連接點(diǎn)(JoinPoint):需要在程序中插入橫切關(guān)注點(diǎn)的點(diǎn),連接點(diǎn)可能是在類初始化、方法調(diào)用、字段調(diào)用或處理異常等等。Spring中只支持方法執(zhí)行連接點(diǎn)。
切入點(diǎn)(Pointcut):一組相關(guān)連接點(diǎn)的集合。
通知(Advice):在連接點(diǎn)上執(zhí)行的行為,增強(qiáng)提供了在AOP中需要在切入點(diǎn)所選擇的連接點(diǎn)處進(jìn)行擴(kuò)展現(xiàn)有行為的手段。包括前置增強(qiáng)(before advice)、后置增強(qiáng) (after advice)、環(huán)繞增強(qiáng) (around advice)。
切面(Aspect):通知和切入點(diǎn)的結(jié)合。
織入(Weaving):織入是一個(gè)過(guò)程,是將切面應(yīng)用到目標(biāo)對(duì)象從而創(chuàng)建出AOP代理對(duì)象的過(guò)程。
代理(Proxy):通過(guò)代理方式來(lái)對(duì)目標(biāo)對(duì)象應(yīng)用切面。AOP代理可以用JDK動(dòng)態(tài)代理或CGLIB代理實(shí)現(xiàn)。
目標(biāo)對(duì)象(Target):需要被織入關(guān)注點(diǎn)的對(duì)象。即被代理的對(duì)象。
實(shí)現(xiàn)AOP的主要設(shè)計(jì)模式就是動(dòng)態(tài)代理。
Spring的動(dòng)態(tài)代理有兩種:一是JDK的動(dòng)態(tài)代理;另一個(gè)是cglib動(dòng)態(tài)代理。
JDK動(dòng)態(tài)代理模擬
JDK動(dòng)態(tài)代理的兩個(gè)核心接口(類)分別是InvocationHandler和Proxy。注意:只能代理接口。
public class TimeHandler implements InvocationHandler { // 目標(biāo)對(duì)象 private Object targetObject; public TimeHandler(Object targetObject){ this.targetObject = targetObject; } @Override //關(guān)聯(lián)的這個(gè)實(shí)現(xiàn)類的方法被調(diào)用時(shí)將被執(zhí)行 /*InvocationHandler接口的方法,proxy表示代理,method表示原對(duì)象被調(diào)用的方法, args表示方法的參數(shù)*/ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object ret=null; try{ System.out.println("方法之前:"+System.currentTimeMillis()); //調(diào)用目標(biāo)方法 ret=method.invoke(targetObject, args); System.out.println("方法之后:"+System.currentTimeMillis()); }catch(Exception e){ e.printStackTrace(); System.out.println("error"); throw e; } return ret; } }
TimeHandler 類實(shí)現(xiàn)了InvocationHandler接口。實(shí)現(xiàn)核心方法invoke,共有3個(gè)參數(shù)。第一個(gè)參數(shù) 生成的代理類實(shí)例,第二個(gè)參數(shù) 目標(biāo)對(duì)象的方法,第三個(gè)參數(shù) 方法的參數(shù)值數(shù)組。
public class ProxyUtil { @SuppressWarnings("unchecked") public static <T> T proxyOne(ClassLoader loader,Class<?>[] clz,InvocationHandler handler){ return (T)Proxy.newProxyInstance(loader, clz, handler); } }
ProxyUtil 類簡(jiǎn)單封裝了一下Proxy.newProxyInstance()方法。該方法也有3個(gè)參數(shù)。第一個(gè)參數(shù)產(chǎn)生代理對(duì)象的類加載器,第二個(gè)參數(shù)目標(biāo)對(duì)象的接口數(shù)組,第三個(gè)參數(shù)就是實(shí)現(xiàn)InvocationHandler接口的類實(shí)例。
public interface UserManager { public void addUser(String userId, String userName); } public class UserManagerImpl implements UserManager { @Override public void addUser(String userId, String userName) { System.out.println("addUser(id:"+userId+",name:"+userName+")"); } } public static void main(String[] args) { UserManager um=new UserManagerImpl(); LogHandler log =new LogHandler(um); um=ProxyUtil.proxyOne(um.getClass().getClassLoader(), um.getClass().getInterfaces(), log); TimeHandler time = new TimeHandler(um); um=ProxyUtil.proxyOne(um.getClass().getClassLoader(), um.getClass().getInterfaces(), time); um.addUser("1111", "張三"); }
為了演示需要,這邊又增加了一個(gè)LogHandler,跟TimeHandler代碼一樣。
CGLIB動(dòng)態(tài)代理模擬
CGLIB動(dòng)態(tài)代理的兩個(gè)核心接口(類)分別是MethodInterceptor和Enhancer。是不是跟JDK動(dòng)態(tài)代理很相似,用法也差不多。但CGLIB可以代理類和接口。注意:不能代理final類。
public class TimeInterceptor implements MethodInterceptor { private Object target; public TimeInterceptor(Object target) { this.target = target; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy invocation) throws Throwable { System.out.println("方法之前:"+System.currentTimeMillis()); Object ret = invocation.invoke(target, args); System.out.println("方法之后:"+System.currentTimeMillis()); return ret; } }
intercept方法4個(gè)參數(shù)。1.生成的代理類實(shí)例。2.被代理對(duì)象的方法引用。3.方法參數(shù)值數(shù)組。4.代理類對(duì)方法的代理引用。
public class ProxyUtil { @SuppressWarnings("unchecked") public static <T> T proxyOne(Class<?> clz,MethodInterceptor interceptor){ return (T)Enhancer.create(clz, interceptor); } }
Enhancer類是CGLib中的字節(jié)碼增強(qiáng)器。
public class UserManage { public void addUser(String userId, String userName) { System.out.println("addUser(id:"+userId+",name:"+userName+")"); } } public static void main(String[] args) { UserManage um = new UserManage(); TimeInterceptor time = new TimeInterceptor(um); um = ProxyUtil.proxyOne(um.getClass(), time); um.addUser("111", "老王"); }
相關(guān)免費(fèi)學(xué)習(xí)推薦:java基礎(chǔ)教程
以上是spring aop原理是什么的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機(jī)

Video Face Swap
使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強(qiáng)大的PHP集成開(kāi)發(fā)環(huán)境

Dreamweaver CS6
視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版
神級(jí)代碼編輯軟件(SublimeText3)