天天看點

【Spring架構】AOP切面程式設計的了解與實作AOP的概念AOP開發術語AOP增強類切入點表達式AOP的實作總結

AOP的概念

AOP(Aspect Oriented Programming),即面向切面程式設計,利用一種稱為"橫切"的技術,剖開封裝的對象内部,并将那些影響了多個類的公共行為封裝到一個可重用子產品,并将其命名為"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻為業務子產品所共同調用的邏輯或責任封裝起來,便于減少系統的重複代碼,降低子產品之間的耦合度,并有利于未來的可操作性和可維護性。

AOP開發術語

  • 連接配接點(Joinpoint):連接配接點是程式類中客觀存在的方法,可被Spring攔截并切入内容。
  • 切入點(Pointcut):被Spring切入連接配接點。
  • 通知、增強(Advice):可以為切入點添加額外功能,分為:前置通知、後置通知、異常通知、環繞通知等。
  • 目标對象(Target):代理的目标對象
  • 引介(Introduction):一種特殊的增強,可在運作期為類動态添加Field和Method。
  • 織入(Weaving):把通知應用到具體的類,進而建立新的代理類的過程。
  • 代理(Proxy):被AOP織入通知後,産生的結果類。
  • 切面(Aspect):由切點和通知組成,将橫切邏輯織入切面所指定的連接配接點中。

AOP增強類

前置增強:MethodBeforeAdvice

後置增強:AfterAdvice

後置增強:AfterReturningAdvice

異常增強:ThrowsAdvice

環繞增強:MethodInterceptor

切入點表達式

比對包名:execution(* com.robot.service.* .*(…))

  • 傳回值任意,com.robot.service包下面的任意類,下面的任意方法,參數任意
<!--比對參數-->
<aop:pointcut id="myPointCut" expression="execution(* *(com.robot.pojo.User))" />
<!--比對方法名(無參)-->
<aop:pointcut id="myPointCut" expression="execution(* save())" />
<!--比對方法名(任意參數)-->
<aop:pointcut id="myPointCut" expression="execution(* save(..))" />
<!--比對傳回值類型-->
<aop:pointcut id="myPointCut" expression="execution(com.robot.pojo.User *(..))" />
<!--比對類名-->
<aop:pointcut id="myPointCut" expression="execution(* com.robot.service.userService.impl.UserServiceImpl.*(..))" />
<!--比對包名-->
<aop:pointcut id="myPointCut" expression="execution(* com.robot.service.*.*(..))" />
<!--比對包名、以及子包名-->
<aop:pointcut id="myPointCut" expression="execution(* com.robot..*.*(..))" />
           

AOP的實作

1、環境搭建

導入依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>
           

在配置檔案中引入AOP命名空間

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       ">
</beans>
           

2、建立切面類

  • 以後置增強為例
  • 基礎AfterReturningAdvice接口,重寫afterReturning方法
public class MyAfterAdvice implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("後置增強:" + method.getName() + " 增強方法:" + o.getClass().getSimpleName());
    }
}
           

3、建立需要被增強的類和接口

  • 将要實作的效果就是,在調用此方法時,此方法會被增強
public interface UserDao {
    int insert();
}
           
public class UserDaoImpl implements UserDao {
    public int insert() {
        System.out.println("UserDaoImpl::insert...");
        return 0;
    }
}
           

4、修改配置檔案

  • 配置aop,expression為切入點表達式
  • 具體行為execution(* com.robot.service.* .*(…)):傳回值任意,com.robot.service包下面的任意類,下面的任意方法,參數任意
<bean name="userService" class="com.robot.service.impl.UserServiceImpl"/>
<bean name="myAfterAdvice" class="com.robot.aop.MyAfterAdvice"/>

<aop:config>
    <aop:pointcut id="myPointcut" expression="execution(* com.robot.service.*.*(..))"/>
    <aop:advisor advice-ref="myAfterAdvice" pointcut-ref="myPointcut"/>
</aop:config>
           

5、測試

  • 調用service層中的方法
public class UserServiceTest {
    @Test
    public void userServiceTest() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.insert();
    }
}
           

結果如下

UserDaoImpl::insert...
後置增強:insert 增強方法:Integer
           

在被調用的insert()方法的後面切入了增強方法,輸出了方法内的語句,說明方法增強成功

總結

  • 通過AOP提供的編碼流程,更便利的定制切面,更友善的定制了動态代理。
  • 進而徹底解決了輔助功能備援的問題;
  • 業務類中職責單一性得到更好保障;
  • 輔助功能也有很好的複用性。