Spring AOP與代理類的執(zhí)行順序級別淺析
關(guān)于 Spring AOP和Aspectj的關(guān)系,兩個都實現(xiàn)了切面編程,Spring AOP更多地是為了Spring框架本身服務(wù)的,而Aspectj具有更強大、更完善的切面功能,我們在寫業(yè)務(wù)時一般使用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項目中提供了@AspecJ
注解,Spring interprets the same annotations @Aspect
as AspectJ 5
Spring AOP提供了定義切面的兩種方式
- schema-based approach : XML-based format 通常不用了
- @AspectJ annotation style:注解形式,起這個名字是因為借鑒了AspectJ項目,其實用的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í)行點,通常代表一個方法的執(zhí)行。
- Advice:Aspect中針對不同Join Point執(zhí)行的操作,包括 around before after 三種advice。很多AOP框架將advice建模成interceptor,在Join Point外層維護(hù)一個 chain of interceptors。
- Pointcut:匹配 Join Points的規(guī)則,如@PointCut("pointcut expression"),滿足point expression的將進(jìn)行切面。
- Target object:被切面的對象。
- AOP proxy:代理,Spring Framework通常使用JDK 動態(tài)代理或CGLIB動態(tài)代理。
- Weaving:linking aspects with other application types or objects to create an advised object. 發(fā)生在編譯、加載或運行時。
Type of advice
- before : @Before
- after returning : @AfterReturning
- after throwing : @AfterThrowing
- after (finally) : @After
- around : @Around
代理順序
當(dāng)一個target object有多個Spring AOP代理時,代理類執(zhí)行的順序有時很重要,比如分布式鎖代理和事務(wù)代理的順序,分布式鎖必須包裹住事務(wù)。
先下結(jié)論:
Spring通過接口或注解來判斷代理的順序,順序級別越低,代理越靠內(nèi)層。順序級別獲取步驟如下:
- 是否實現(xiàn)
org.springframework.core.Ordered
接口 - 是否注解了
org.springframework.core.annotation.Order
注解 - 是否注解了
javax.annotation.Priority
注解 - 如果都沒有,默認(rèn)最低優(yōu)先級
LOWEST_PRECEDENCE = Integer.MAX_VALUE
,如@Transanctional
注解就是最低級別
優(yōu)先級定義范圍在Integer.MIN_VALUE
到 Integer.MAX_VALUE
(參見Orderd
接口)。越小,優(yōu)先級越高,越在外層先執(zhí)行。
注解方式生成代理類是通過BeanPostProcessor
實現(xiàn)的,由AspectJAwareAdvisorAutoProxyCreator
完成,該類實現(xiàn)了BeanPostProcessor
。
注意到該類有一個Comparator
類字段。最終優(yōu)先級由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) { // 父類,判斷是否實現(xiàn)了Orderd接口 // (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null) Integer order = super.findOrder(obj); if (order != null) { return order; } // 沒有實現(xiàn)則繼續(xù)搜尋@Order和@Priority注解 // 如果返回null,表示找不到,會返回父類執(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)先級,沒有則返回null return order; } }
到此這篇關(guān)于Spring AOP與代理類的執(zhí)行順序級別淺析的文章就介紹到這了,更多相關(guān)Spring AOP與代理類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Web實現(xiàn)session過期后自動跳轉(zhuǎn)到登陸頁功能【基于過濾器】
這篇文章主要介紹了Java Web實現(xiàn)session過期后自動跳轉(zhuǎn)到登陸頁功能,涉及java過濾器針對session的判斷與跳轉(zhuǎn)相關(guān)操作技巧,需要的朋友可以參考下2017-11-11Javaweb-HttpServletResponse的sendRedirectch重定向方式
這篇文章主要介紹了Javaweb-HttpServletResponse的sendRedirectch重定向方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09一文教會你用mybatis查詢數(shù)據(jù)庫數(shù)據(jù)
MyBatis本身是一個數(shù)據(jù)庫連接框架,可以認(rèn)為是JDBC的升級版,下面這篇文章主要給大家介紹了關(guān)于mybatis查詢數(shù)據(jù)庫數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Springboot項目異常處理及返回結(jié)果統(tǒng)一
這篇文章主要介紹了Springboot項目異常處理及返回結(jié)果統(tǒng)一,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-08-08