1. 程式人生 > 實用技巧 >Spring(3):AOP面向切面程式設計

Spring(3):AOP面向切面程式設計

一,AOP介紹

AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數語言程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率

1,主要功能

日誌記錄,效能統計,安全控制,事務處理,異常處理等等

2,主要意圖

將日誌記錄,效能統計,安全控制,事務處理,異常處理等程式碼從業務邏輯程式碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的程式碼

3,AOP在Spring中的作用

提供宣告式事務;允許使用者自定義切面
橫切關注點:跨越應用程式多個模組的方法或功能。即是,與我們業務邏輯無關的,但是我們需要關注的部分,就是橫切關注點。如日誌 , 安全 , 快取 , 事務等等 ....

切面(ASPECT) 橫切關注點 被模組化 的特殊物件,即,它是一個類
通知(Advice) 切面必須要完成的工作。即,它是類中的一個方法
目標(Target) 被通知物件
代理(Proxy) 向目標物件應用通知之後建立的物件
切入點(PointCut) 切面通知 執行的 “地點”的定義
連線點(JointPoint) 與切入點匹配的執行點





二,使用SpringAPI實現AOP

1,介面(User)

1 //抽象角色
2 public interface User {
3 
4 public void show();
5 
6 }

2,實現類(UserImpl)

1 //真實角色
2 public class UserImpl implements User{
3 
4 public void show() {
5 System.out.println("這是一個show方法");
6 }
7 
8 }

3,定義日誌增加類實現

1.Log

 1 import org.springframework.aop.MethodBeforeAdvice;
2 import java.lang.reflect.Method; 3 4 public class Log implements MethodBeforeAdvice { 5 6 //method:被呼叫目標物件的方法 7 //args:要被呼叫的方法的引數 8 //target:被呼叫的目標物件 9 public void before(Method method, Object[] args, Object target) throws Throwable { 10 System.out.println("目標物件:"+target.getClass().getName()+"的" 11 +method.getName()+"方法被執行了"); 12 } 13 }

2.AfterLog

 1 import org.springframework.aop.AfterReturningAdvice;
 2 import java.lang.reflect.Method;
 3 
 4 public class AfterLog implements AfterReturningAdvice {
 5 
 6 //returnValue : 返回值
 7 //method : 被呼叫目標物件的方法
 8 //args : 要被呼叫的方法的引數
 9 //target : 被呼叫的目標物件
10 
11 public void afterReturning(Object returnValue, Method method, 
12 Object[] args, Object target) throws Throwable {
13 System.out.println("執行了目標物件:"+target.getClass().getName()+"的"
14 +method.getName()+"方法,返回值:"+returnValue);
15 }
16 
17 }

4,編寫Spring核心配置檔案(logbeans.xml)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4 xmlns:aop="http://www.springframework.org/schema/aop"
 5 xsi:schemaLocation="http://www.springframework.org/schema/beans
 6 http://www.springframework.org/schema/beans/spring-beans.xsd
 7 http://www.springframework.org/schema/aop
 8 http://www.springframework.org/schema/aop/spring-aop.xsd">
 9 
10 <!--註冊bean-->
11 <bean id="User" class="service.UserImpl"/>
12 
13 <!--註冊日誌的bean-->
14 <bean id="Log" class="log.Log"/>
15 <bean id="AfterLog" class="log.AfterLog"/>
16 
17 <!--使用spring的AOP切入-->
18 <aop:config>
19 <!--切入點-->
20 <aop:pointcut id="pointcut" expression="execution(* service.UserImpl.*(..))"/>
21 <!--執行通知,增強-->
22 <aop:advisor advice-ref="Log" pointcut-ref="pointcut"/>
23 <aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/>
24 </aop:config>
25 
26 </beans>

【注意點】

5,編寫測試類(AopTest)

 1 public class AopTest {
 2 @Test
 3 public void Test01(){
 4 ClassPathXmlApplicationContext context = 
 5 new ClassPathXmlApplicationContext("logbeans.xml");
 6 User user = (User) context.getBean("User");
 7 
 8 user.show();
 9 }
10 }

【注意點:測試時需要匯入AOP的包在你的pom.xml中】

1 <dependency>
2 <groupId>org.aspectj</groupId>
3 <artifactId>aspectjweaver</artifactId>
4 <version>1.8.9</version>
5 </dependency>

6,執行結果

三,自定義類實現AOP

和使用SpringAPI實現AOP一樣,先要建立抽象角色和真實角色,我們這裡的介面與實體類和前面一樣

1,自定一個Aop增強類:也就是所謂的切面

 1 public class Diy {
 2 
 3 public void before(){
 4 System.out.println("show方法執行前");
 5 }
 6 
 7 public void after(){
 8 System.out.println("show方法執行後");
 9 }
10 }

2,配置檔案(diybeans.xml)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:aop="http://www.springframework.org/schema/aop"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans
 6         http://www.springframework.org/schema/beans/spring-beans.xsd
 7         http://www.springframework.org/schema/aop
 8         http://www.springframework.org/schema/aop/spring-aop.xsd">
 9 
10     <!--註冊bean-->
11     <bean id="User" class="service.UserImpl"/>
12 
13     <!--自定義的AOP增強類-->
14     <bean id="Diy" class="diy.Diy"/>
15 
16     <!--編寫aop配置檔案-->
17     <aop:config>
18         
19         <!--切面-->
20         <aop:aspect ref="Diy">
21             <!--切入點-->
22         <aop:pointcut id="diyPointCut" expression="execution(* service.UserImpl.*(..))"/>
23             <aop:before method="before" pointcut-ref="diyPointCut"/>
24             <aop:after method="after" pointcut-ref="diyPointCut"/>
25         </aop:aspect>
26         
27     </aop:config>
28 
29 </beans>

3,測試類

 1 public class AopTest {
 2 @Test
 3 public void Test02(){
 4 ClassPathXmlApplicationContext context = 
 5 new ClassPathXmlApplicationContext("diybeans.xml");
 6 User user = (User) context.getBean("User");
 7 
 8 user.show();
 9 }
10 }

4,執行結果

四,使用註解實現AOP

介面和實體類不變

1,編寫AOP增強類

 1 @Aspect
 2 public class Anno {
 3 
 4 @Before("execution(* service.UserImpl.*(..))")
 5 public void before(){
 6 System.out.println("show方法執行前");
 7 }
 8 
 9 @After("execution(* service.UserImpl.*(..))")
10 public void after(){
11 System.out.println("show方法執行後");
12 }
13 
14 }

【注意點】


2,配置檔案(annobeans.xml)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4 xmlns:aop="http://www.springframework.org/schema/aop"
 5 xsi:schemaLocation="http://www.springframework.org/schema/beans
 6 http://www.springframework.org/schema/beans/spring-beans.xsd
 7 http://www.springframework.org/schema/aop
 8 http://www.springframework.org/schema/aop/spring-aop.xsd">
 9 
10 <!--註冊bean-->
11 <bean id="User" class="service.UserImpl"/>
12 
13 <!--註冊日誌的bean-->
14 <bean id="Log" class="log.Log"/>
15 <bean id="AfterLog" class="log.AfterLog"/>
16 
17 <!--使用spring的AOP切入-->
18 <aop:config>
19 <!--切入點-->
20 <aop:pointcut id="pointcut" expression="execution(* service.UserImpl.*(..))"/>
21 <!--執行通知,增強-->
22 <aop:advisor advice-ref="Log" pointcut-ref="pointcut"/>
23 <aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/>
24 </aop:config>
25 
26 </beans>

3,測試類

 1 public class AopTest {
 2 @Test
 3 public void Test03(){
 4 ClassPathXmlApplicationContext context = 
 5 new ClassPathXmlApplicationContext("annobeans.xml");
 6 User user = (User) context.getBean("User");
 7 
 8 user.show();
 9 }
10 }

4,執行結果

五,AOP小結

  • 本質就是動態代理
  • 需要到一個包,用來進行aop織入的包: aspectjweaver
  • 注意別遺漏了切面
  • 三種實現AOP的方法
  • 使用SpringAPI來實現AOP
  • 使用自定義類來實現AOP
  • 使用註解實現AOP