Spring 除 IoC 容器外的另一個核心功能是 AOP彤叉,面向切面編程是對編程結構的另一種思考梆靖。
一、概述
AOP 提供一種通用的擴展機制心铃,在業(yè)務操作前后提供一些切面的操作满着,這些操作通常是和業(yè)務無關的谦炒,例如:日志記錄贯莺、性能統(tǒng)計、安全控制宁改、事務處理缕探、異常處理等。
1. AOP 術語
AOP(Aspect Oriented Programming)面向切面編程的概念比較抽象还蹲,主要涉及下面這些術語:
- Aspect(切面):切入一個或多個類的模塊
- Join point(連接點):程序執(zhí)行的節(jié)點爹耗,例如執(zhí)行方法或處理異常
- Advice(通知):切面在連接點執(zhí)行的動作,例如前置通知
- Pointcut(切點):用于匹配連接點谜喊,一般通過表達式匹配
- Target object(目標對象):被切入的對象潭兽,可以被一個或多個切面切入
使用 AOP 時,需要定義實現(xiàn)切面的類斗遏,在切面中指定切點和通知山卦。
一個目標類可以被多個切面切入,多個切面也可以切入一個目標類诵次。
切面實現(xiàn)的本質是一個或多個基于連接點的攔截器账蓉。
2. 通知類型
Spring AOP 提供了下面五種通知類型:
- Before advice(前置通知):連接點前面執(zhí)行,不能終止后續(xù)流程藻懒,除非拋異常
- After returning advice(后置通知):連接點正常返回時執(zhí)行,有異常不執(zhí)行
- Around advice(環(huán)繞通知):圍繞連接點前后執(zhí)行视译,也能捕獲處理異常
- After advice(最終通知):連接點退出時執(zhí)行嬉荆,無論是正常退出還是異常退出
- After throwing advice(異常通知):連接點方法拋出異常時執(zhí)行
AOP 的連接點一般是指目標類的方法,五種通知類型執(zhí)行的節(jié)點如下:
二酷含、動態(tài)代理
Spring AOP 底層是基于動態(tài)代理實現(xiàn)的鄙早,對實現(xiàn)接口的類進行代理,默認使用 JDK 動態(tài)代理椅亚,對沒實現(xiàn)接口的類限番,使用 CGLIB 動態(tài)代理。
1. JDK 動態(tài)代理
JDK 動態(tài)代理通過實現(xiàn)接口生成代理類呀舔,使用攔截器加反射機制生成弥虐。
public static void main(String[] args) {
// JDK Proxy
DemoService demoService = new DemoServiceImpl();
DemoServiceProxy proxy = new DemoServiceProxy();
DemoService proxyTarget = (DemoService) proxy.getTarget(demoService);
proxyTarget.doService();
}
2. CGLIB 動態(tài)代理
CGLIB 動態(tài)代理通過繼承生成代理子類,使用字節(jié)碼技術生成媚赖。
通過子類對父類的方法進行重寫來實現(xiàn)代理霜瘪,因此,對 final
修飾的方法不能代理惧磺。
public static void main(String[] args) {
// CGLib Proxy
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(DemoServiceImpl.class);
enhancer.setCallback(new DemoServiceInterceptor());
DemoService service = (DemoService) enhancer.create();
service.doService();
}
強制使用 CGLIB 代理
Spring AOP 中的目標類不管有沒有實現(xiàn)接口颖对,都可以通過配置來強制使用 CGLIB 代理方式。
基于 XML 配置:
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>
<!-- 或者 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
基于注解配置:
@EnableAspectJAutoProxy(proxyTargetClass = true)
三磨隘、附錄
1. 示例代碼
Gitee 倉庫:https://gitee.com/code_artist/spring
項目模塊:spring-aop
示例路徑:cn.codeartist.spring.aop.proxy
最新文章關注 CodeArtist 碼匠公眾號缤底。
更多:Spring高效實踐專欄