Spring AOP與代理類的執(zhí)行順序級(jí)別淺析
關(guān)于 Spring AOP和Aspectj的關(guān)系,兩個(gè)都實(shí)現(xiàn)了切面編程,Spring AOP更多地是為了Spring框架本身服務(wù)的,而Aspectj具有更強(qiáng)大、更完善的切面功能,我們在寫業(yè)務(wù)時(shí)一般使用AspectJ。不過他們的概念、原理都差不多。
Spring AOP說:
the Spring Framework’s AOP functionality is normally used in conjunction with the Spring IoC container. Aspects are configured using normal bean definition syntax (although this allows powerful “autoproxying” capabilities): this is a crucial difference from other AOP implementations. There are some things you cannot do easily or efficiently with Spring AOP, such as advise very fine-grained objects (such as domain objects typically): AspectJ is the best choice in such cases. However, our experience is that Spring AOP provides an excellent solution to most problems in enterprise Java applications that are amenable to AOP
Spring AOP currently supports only method execution join points (advising the execution of methods on Spring beans). Field interception is not implemented, although support for field interception could be added without breaking the core Spring AOP APIs. If you need to advise field access and update join points, consider a language such as AspectJ.
Spring AOP will never strive to compete with AspectJ to provide a comprehensive AOP solution
AspectJ項(xiàng)目中提供了@AspecJ
注解,Spring interprets the same annotations @Aspect
as AspectJ 5
Spring AOP提供了定義切面的兩種方式
- schema-based approach : XML-based format 通常不用了
- @AspectJ annotation style:注解形式,起這個(gè)名字是因?yàn)榻梃b了AspectJ項(xiàng)目,其實(shí)用的Spring AOP的注解是@Aspect沒有J
注解案例:
@Aspect @Component public class NotVeryUsefulAspect { @Pointcut("execution(* transfer(..))")// the pointcut expression private void anyOldTransfer() {}// the pointcut signature @Before("execution(* com.xyz.myapp.dao.*.*(..))") public void doAccessCheck() { // ... } @AfterReturning( pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", returning="retVal") public void doAccessCheck(Object retVal) { // ... } @AfterThrowing( pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", throwing="ex") public void doRecoveryActions(DataAccessException ex) { // ... } @After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") public void doReleaseLock() { // ... } @Around("com.xyz.myapp.SystemArchitecture.businessService()") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { // start stopwatch Object retVal = pjp.proceed(); // stop stopwatch return retVal; } }
AOP概念
- Aspect:cut cross multiple classes. Spring AOP通過 schema-based approach 或 @AspectJ annotation style 兩種方式定義切面。
- Join Point:程序執(zhí)行點(diǎn),通常代表一個(gè)方法的執(zhí)行。
- Advice:Aspect中針對(duì)不同Join Point執(zhí)行的操作,包括 around before after 三種advice。很多AOP框架將advice建模成interceptor,在Join Point外層維護(hù)一個(gè) chain of interceptors。
- Pointcut:匹配 Join Points的規(guī)則,如@PointCut("pointcut expression"),滿足point expression的將進(jìn)行切面。
- Target object:被切面的對(duì)象。
- AOP proxy:代理,Spring Framework通常使用JDK 動(dòng)態(tài)代理或CGLIB動(dòng)態(tài)代理。
- Weaving:linking aspects with other application types or objects to create an advised object. 發(fā)生在編譯、加載或運(yùn)行時(shí)。
Type of advice
- before : @Before
- after returning : @AfterReturning
- after throwing : @AfterThrowing
- after (finally) : @After
- around : @Around
代理順序
當(dāng)一個(gè)target object有多個(gè)Spring AOP代理時(shí),代理類執(zhí)行的順序有時(shí)很重要,比如分布式鎖代理和事務(wù)代理的順序,分布式鎖必須包裹住事務(wù)。
先下結(jié)論:
Spring通過接口或注解來判斷代理的順序,順序級(jí)別越低,代理越靠內(nèi)層。順序級(jí)別獲取步驟如下:
- 是否實(shí)現(xiàn)
org.springframework.core.Ordered
接口 - 是否注解了
org.springframework.core.annotation.Order
注解 - 是否注解了
javax.annotation.Priority
注解 - 如果都沒有,默認(rèn)最低優(yōu)先級(jí)
LOWEST_PRECEDENCE = Integer.MAX_VALUE
,如@Transanctional
注解就是最低級(jí)別
優(yōu)先級(jí)定義范圍在Integer.MIN_VALUE
到 Integer.MAX_VALUE
(參見Orderd
接口)。越小,優(yōu)先級(jí)越高,越在外層先執(zhí)行。
注解方式生成代理類是通過BeanPostProcessor
實(shí)現(xiàn)的,由AspectJAwareAdvisorAutoProxyCreator
完成,該類實(shí)現(xiàn)了BeanPostProcessor
。
注意到該類有一個(gè)Comparator
類字段。最終優(yōu)先級(jí)由AnnotationAwareOrderComparator
來判斷:
public class AnnotationAwareOrderComparator extends OrderComparator { /** * Shared default instance of {@code AnnotationAwareOrderComparator}. */ public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator(); @Override @Nullable protected Integer findOrder(Object obj) { // 父類,判斷是否實(shí)現(xiàn)了Orderd接口 // (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null) Integer order = super.findOrder(obj); if (order != null) { return order; } // 沒有實(shí)現(xiàn)則繼續(xù)搜尋@Order和@Priority注解 // 如果返回null,表示找不到,會(huì)返回父類執(zhí)行g(shù)etOrder方法返回Ordered.LOWEST_PRECEDENCE return findOrderFromAnnotation(obj); } @Nullable private Integer findOrderFromAnnotation(Object obj) { ... // 找@Order和@Priority注解 Integer order = OrderUtils.getOrderFromAnnotations(element, annotations); // 如果該類沒有注解,遞歸找被代理類 if (order == null && obj instanceof DecoratingProxy) { return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass()); } // 被代理類有則返回優(yōu)先級(jí),沒有則返回null return order; } }
到此這篇關(guān)于Spring AOP與代理類的執(zhí)行順序級(jí)別淺析的文章就介紹到這了,更多相關(guān)Spring AOP與代理類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Web實(shí)現(xiàn)session過期后自動(dòng)跳轉(zhuǎn)到登陸頁功能【基于過濾器】
這篇文章主要介紹了Java Web實(shí)現(xiàn)session過期后自動(dòng)跳轉(zhuǎn)到登陸頁功能,涉及java過濾器針對(duì)session的判斷與跳轉(zhuǎn)相關(guān)操作技巧,需要的朋友可以參考下2017-11-11Java實(shí)現(xiàn)學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Javaweb-HttpServletResponse的sendRedirectch重定向方式
這篇文章主要介紹了Javaweb-HttpServletResponse的sendRedirectch重定向方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09一文教會(huì)你用mybatis查詢數(shù)據(jù)庫數(shù)據(jù)
MyBatis本身是一個(gè)數(shù)據(jù)庫連接框架,可以認(rèn)為是JDBC的升級(jí)版,下面這篇文章主要給大家介紹了關(guān)于mybatis查詢數(shù)據(jù)庫數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Springboot項(xiàng)目異常處理及返回結(jié)果統(tǒng)一
這篇文章主要介紹了Springboot項(xiàng)目異常處理及返回結(jié)果統(tǒng)一,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08