一、什么是AOP
AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期間動態代理實作程式功能的統一維護的一種技術,AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函式式編程的一種衍生范型,利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率,
二、AOP的一些概念
1.Aspect(切面):切面是通知和切入點的結合,
2.Join point(連接點):與切入點匹配的執行點,例如執行方法或處理例外,在SpringAOP 中,連接點始終表示方法執行,
3.Advice(通知):在切面中需要完成的作業,
4.Pointcut(切入點):切入通知執行的位置,
5.Target(目標):被通知的物件,
6. proxy(代理):向目標物件應用通知之后創建的物件,
7.Introduction(引入):向現有類添加新的方法或屬性,
8.Weaving(織入):將各個方面與其他應用程式型別或物件鏈接起來,以創建通知的物件,
三、AOP的三種實作方法
首先我們需要匯入依賴:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.9.1</version> </dependency>
1.通過SpringAPI介面進行實作
SpringAOP有五種通知方式,也有對應的介面:
Before:前置通知,在目標方法呼叫前通知,對應介面:MethodBeforeAdvice;
After:后置通知,在目標方法回傳或例外后通知,對應介面:AfterReturningAdvice;
AfterReturning:后置回傳通知,在目標方法回傳后通知,對應介面:AfterReturningAdvice;
AfterThrowing:例外通知,在目標方法拋出例外后通知,對應介面:ThrowsAdvice;
Around:環繞通知:通知方法會將目標方法包裹起來,對應介面:MethodInterceptor;
我們下面以具體的例子來展示:
(1)定義一個介面
package com.jms.service; public interface UserService { void create(); void read(); void update(); void delete(); }
(2)介面的實作類
package com.jms.service; public class UserServiceImpl implements UserService{ @Override public void create() { System.out.println("建立了一個用戶資訊"); } @Override public void read() { System.out.println("讀取了一個用戶資訊"); } @Override public void update() { System.out.println("更新了一個用戶資訊"); } @Override public void delete() { System.out.println("洗掉了了一個用戶資訊"); } }
(3)建立兩個類分別繼承前置通知和后置回傳通知的介面
package com.jms.log; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class beforeLog implements MethodBeforeAdvice { @Override //method:要執行目標物件的方法 //args:引數 //target:目標物件 public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("[Debug]" + target.getClass().getName() + "的" + method.getName() + "執行..."); } }
package com.jms.log; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class afterLog implements AfterReturningAdvice{ //returnValue:回傳值 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("[Debug]" + target.getClass().getName() + "的" + method.getName() + "執行完成,回傳了" + returnValue); } }
(4)xml組態檔
注冊bean,并且配置aop
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.jms.service.UserServiceImpl"/> <bean id="beforeLog" class="com.jms.log.beforeLog"/> <bean id="afterLog" class="com.jms.log.afterLog"/> <!--方法一:使用SpringAPI介面--> <!--aop配置--> <aop:config> <!--pointcut:切入點 expression:運算式 --> <aop:pointcut id="pointcut" expression="execution(* com.jms.service.UserServiceImpl.*(..))"/> <!--執行環繞增加--> <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
(5)測驗
@Test public void test1() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); /* UserServiceImpl userService = applicationContext.getBean("userService", UserServiceImpl.class)這樣執行會報錯 因為動態代理代理的是介面,所以必須獲取介面 */ UserService userService = applicationContext.getBean("userService", UserService.class); userService.create(); }
測驗結果如下:

2.自定義類、自定義切面實作
介面以及實作類都與上面相同
(1)自定義切面類
package com.jms.diy; public class diyAspect { public void before() { System.out.println("[Debug]方法執行..."); } public void after() { System.out.println("[Debug]方法執行完成"); } }
切面類中自定義通知方法
(2)xml組態檔
注入切面類的Bean,配置AOP
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.jms.service.UserServiceImpl"/> <!--方法二:自定義類,自定義切面--> <bean id="diyAspect" class="com.jms.diy.diyAspect"/> <aop:config> <!--自定義切面--> <aop:aspect ref="diyAspect"> <!--切入點--> <aop:pointcut id="pointcut1" expression="execution(* com.jms.service.UserServiceImpl.*(..))"/> <aop:after method="after" pointcut-ref="pointcut1"/> <aop:before method="before" pointcut-ref="pointcut1"/> </aop:aspect> </aop:config> </beans>
(3)測驗如下

3.通過注解實作
這種實作其實是第二種的注解方式
(1)自定義切面類
package com.jms.diy; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class annotationAspect { @Before("execution(* com.jms.service.UserServiceImpl.*(..))") public void before() { System.out.println("[Debug]方法前置增強"); } @After("execution(* com.jms.service.UserServiceImpl.*(..))") public void after() { System.out.println("[Debug]方法后置增強"); } }
(2)此處還是采用xml配置,也可以采用java類配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean id="userService" class="com.jms.service.UserServiceImpl"/> <!--方法三:注解--> <!--增加注解支持--> <context:annotation-config/> <context:component-scan base-package="com.jms"/> <aop:aspectj-autoproxy/> </beans>
(3)測驗

(本文僅作個人學習記錄用,如有紕漏敬請指正)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/510659.html
標籤:Java
