<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
AOP,即面向切面程式設計是很常用的技術,特別是在Java Web開發中。而最流行的AOP框架分別是Spring AOP和AspectJ。
Spring AOP是基於Spring IoC實現的,它解決大部分常見的需求,但它並不是一個完整的AOP解決方案。對於非Spring容器管理的物件,它更沒有辦法了。而AspectJ旨在提供完整的AOP方案,因此也會更復雜。
兩者織入方式有極大的不同,這也是它們的本質區別,它們實現代理的方式不同。
AspectJ是在執行前織入的,分為三類:
因此需要AspectJ編譯器(ajc)的支援。
而Spring AOP是執行時織入的,主要使用了兩種技術:JDK動態代理和CGLIB代理。對於介面使用JDK Proxy,而繼承的使用CGLIB。
因為織入方式的區別,兩者所支援的Joinpoint也是不同的。像final的方法和靜態方法,無法通過動態代理來改變,所以Spring AOP無法支援。但AspectJ是直接在執行前織入實際的程式碼,所以功能會強大很多。
Joinpoint | Spring AOP Supported | AspectJ Supported |
---|---|---|
Method Call | No | Yes |
Method Execution | Yes | Yes |
Constructor Call | No | Yes |
Constructor Execution | No | Yes |
Static initializer execution | No | Yes |
Object initialization | No | Yes |
Field reference | No | Yes |
Field assignment | No | Yes |
Handler execution | No | Yes |
Advice execution | No | Yes |
編譯織入會比較執行時織入快很多,Spring AOP是使用代理模式在執行時才建立對應的代理類,效率沒有AspectJ高。
因為AspectJ比較強大,在專案中應用會更多,所以這裡只介紹它與Spring Boot的整合。
引入以下依賴,在Spring Boot基礎上加了Lombok和aspectj:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <scope>provided</scope> </dependency> </dependencies>
為了驗證AOP的功能,我們新增一個TestController,它有一個處理Get請求的方法,同時會呼叫private的成員方法和靜態方法:
@RestController @RequestMapping("/test") @Slf4j public class TestController { @GetMapping("/hello") public String hello() { log.info("------hello() start---"); test(); staticTest(); log.info("------hello() end---"); return "Hello, pkslow."; } private void test() { log.info("------test() start---"); log.info("test"); log.info("------test() end---"); } private static void staticTest() { log.info("------staticTest() start---"); log.info("staticTest"); log.info("------staticTest() end---"); } }
設定切面如下:
@Aspect @Component @Slf4j //@EnableAspectJAutoProxy public class ControllerAspect { @Pointcut("execution(* com.pkslow.springboot.controller..*.*(..))") private void testControllerPointcut() { } @Before("testControllerPointcut()") public void doBefore(JoinPoint joinPoint){ log.info("------pkslow aop doBefore start------"); String method = joinPoint.getSignature().getName(); String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName(); log.info("Method: {}.{}" ,declaringTypeName, method); log.info("------pkslow aop doBefore end------"); } @Around("testControllerPointcut()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { log.info("------pkslow aop doAround start------"); long start = System.nanoTime(); Object obj = joinPoint.proceed(); long end = System.nanoTime(); log.info("Execution Time: " + (end - start) + " ns"); log.info("------pkslow aop doAround end------"); return obj; } }
@Pointcut
定義哪些類和方法會被捕抓來代理,這裡設定的是controller下的所有方法。
而@Before
和@Around
則定義了一些處理邏輯。@Before
是列印了方法名,而@Around
是做了一個計時。
注意:是不需要設定@EnableAspectJAutoProxy
的。
因為是需要編譯時織入程式碼,所以需要maven外掛的支援:github.com/mojohaus/as…
設定好pom.xml檔案即可。
然後執行命令打包:
mvn clean package
這時會顯示一些織入資訊,大致如下:
[INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:14) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:14) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:28) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java)) [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:28) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
看到以上資訊,說明成功織入了程式碼,具體可以檢視生成的class檔案。
可以看到有許多程式碼都不是我們寫的,而是織入生成。
編譯成功後,我們就執行程式碼。如果是通過IDEA來執行,則在執行前不需要再build了,因為已經通過maven build過了包。通過IDEA自帶的編譯器build,可能無法織入。或者選擇ajc作為編譯器。
具體請參考:IDEA啟動Springboot但AOP失效
存取如下:
GET http://localhost:8080/test/hello
則紀錄檔如下,成功實現AOP功能:
遇到錯誤:
ajc Syntax error, annotations are only available if source level is 1.5 or greater
需要設定外掛:
<complianceLevel>${java.version}</complianceLevel> <source>${java.version}</source> <target>${java.version}</target>
可能還會遇到無法識別Lombok的錯誤,設定如下則解決該問題:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <complianceLevel>${java.version}</complianceLevel> <source>${java.version}</source> <target>${java.version}</target> <proc>none</proc> <showWeaveInfo>true</showWeaveInfo> <forceAjcCompile>true</forceAjcCompile> <sources/> <weaveDirectories> <weaveDirectory>${project.build.directory}/classes</weaveDirectory> </weaveDirectories> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin>
AOP場景應用特別多,還是需要掌握的。
程式碼請看GitHub: github.com/LarryDpk/pk…
以上就是Spring AOP與AspectJ的對比及應用詳解的詳細內容,更多關於Spring AOP對比AspectJ應用的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45