Spring AOP的實現(xiàn)原理及應用場景(通過動態(tài)代理)

來源:guguoyu.blog.csdn.net/article/details/80868392
AOP的作用 AOP應用場景 AOP的實現(xiàn)原理 JDK動態(tài)代理 Cglib動態(tài)代理
AOP的作用
作用:在不修改源代碼的情況下,可以實現(xiàn)功能的增強。
傳統(tǒng)的縱向體系代碼復用:
橫向抽取機制(AOP思想):
AOP 思想:基于代理思想,對原來目標對象,創(chuàng)建代理對象,在不修改原對象代碼情況下,通過代理對象,調(diào)用增強功能的代碼,從而對原有業(yè)務方法進行增強 !
AOP應用場景
場景一:記錄日志 場景二:監(jiān)控方法運行時間 (監(jiān)控性能) 場景三:權(quán)限控制 場景四:緩存優(yōu)化 (第一次調(diào)用查詢數(shù)據(jù)庫,將查詢結(jié)果放入內(nèi)存對象, 第二次調(diào)用, 直接從內(nèi)存對象返回,不需要查詢數(shù)據(jù)庫 ) 場景五:事務管理 (調(diào)用方法前開啟事務, 調(diào)用方法后提交關(guān)閉事務 )
AOP的實現(xiàn)原理
那Spring中AOP是怎么實現(xiàn)的呢?Spring中AOP的有兩種實現(xiàn)方式:1、JDK動態(tài)代理 2、Cglib動態(tài)代理
JDK動態(tài)代理
1.引入依賴,有spring,單元測,日志管理
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- 單元測試 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
2.UserDao接口
public interface UserDao {
public void saveUser();
}
3.UserDao實現(xiàn)類
public class UserDaoImpl implements UserDao {
@Override
public void saveUser() {
System.out.println("持久層:用戶保存");
}
}
4.動態(tài)代理
@Test
public void test1() {
final UserDao userDao = new UserDaoImpl();
// newProxyInstance的三個參數(shù)解釋:
// 參數(shù)1:代理類的類加載器,同目標類的類加載器
// 參數(shù)2:代理類要實現(xiàn)的接口列表,同目標類實現(xiàn)的接口列表
// 參數(shù)3:回調(diào),是一個InvocationHandler接口的實現(xiàn)對象,當調(diào)用代理對象的方法時,執(zhí)行的是回調(diào)中的invoke方法
//proxy為代理對象
UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), new InvocationHandler() {
@Override
// 參數(shù)proxy:被代理的對象
// 參數(shù)method:執(zhí)行的方法,代理對象執(zhí)行哪個方法,method就是哪個方法
// 參數(shù)args:執(zhí)行方法的參數(shù)
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("記錄日志");
Object result = method.invoke(userDao, args);
return result;
}
});
//代理對象執(zhí)行方法
proxy.saveUser();
}
5.結(jié)果
在沒有修改原有類的代碼的情況下,對原有類的功能進行了增強
Cglib動態(tài)代理
在實際開發(fā)中,可能需要對沒有實現(xiàn)接口的類增強,用JDK動態(tài)代理的方式就沒法實現(xiàn)。采用Cglib動態(tài)代理可以對沒有實現(xiàn)接口的類產(chǎn)生代理,實際上是生成了目標類的子類來增強。? 首先,需要導入Cglib所需的jar包。提示:spring已經(jīng)集成了cglib,我們已經(jīng)導入了spring包,所以不需要再導入其它包了。1.創(chuàng)建LinkManDao類,沒有實現(xiàn)任何接口
public class LinkManDao {
public void save(){
System.out.println("持久層:聯(lián)系人保存....");
}
}
2.動態(tài)代理
@Test
public void test2() {
final LinkManDao linkManDao = new LinkManDao();
// 創(chuàng)建cglib核心對象
Enhancer enhancer = new Enhancer();
// 設置父類
enhancer.setSuperclass(linkManDao.getClass());
// 設置回調(diào)
enhancer.setCallback(new MethodInterceptor() {
/**
* 當你調(diào)用目標方法時,實質(zhì)上是調(diào)用該方法
* intercept四個參數(shù):
* proxy:代理對象
* method:目標方法
* args:目標方法的形參
* methodProxy:代理方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
System.out.println("記錄日志");
Object result = method.invoke(linkManDao, args);
return result;
}
});
// 創(chuàng)建代理對象
LinkManDao proxy = (LinkManDao) enhancer.create();
proxy.save();
}
推薦閱讀:
不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設PPT)
企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案
論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?
企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!
【中臺實踐】華為大數(shù)據(jù)中臺架構(gòu)分享.pdf

