06 Spring AOP

1、AOP概念

AOP就是面向切面編程,在原有方法的前邊或者後邊增加一些業務邏輯代碼。

相關術語:

1、連接點:程序執行過程中的某個時間點。

2、切入點:就是需要切面編程的連接點。

3、通知:是在切入點前邊或者後邊要執行的一段代碼,通知有分爲:前置通知,後置通知,異常通知,最終通知和環繞通知等。

4、切面:指封裝切入點和通知的一個類。

5、目標對象:被增強的對象。

2、通知類型說明

1、前置通知:在目標方法執行前實施增強。

2、後置返回通知:在目標方法執行後執行,如果產生了異常,則不會被執行。

3、後置最終通知:在目標方法執行後執行,有異常,也會被執行的通知。

4、異常通知:當目標方法執行過程中產生異常,則執行的通知。

5、環繞通知:在目標方法執行前和目標方法執行後執行的通知。

6、引入通知:在目標類中增加一些新的方法和屬性,用來對目標類進行擴展。

3、AspectJ切入表表達式

基本語法:

@Pointcut(value="execution(modifiers-pattern? ret-type-pattern declaring-type-pattern.methodName-pattern(param-pattern) throws-pattern?)")

1)末尾有?的代表可以省略。

2)modifiers-pattern? 目標方法的修飾符匹配符,如public , private

3)ret-type-pattern 目標方法返回值匹配符,如void、string等,* 代表所有類型。

4)declaring-type-pattern 目標方法類路徑匹配符,如cn.sjxy.service.UserService,*代表所有類型

5)methodName-pattern 目標方法名稱匹配符,例如Insert,Update,*代表所有方法名。

6)param-pattern 目標方法參數匹配符,(..)代表所有的參數,包含無參方法。

7)throws-pattern? 目標方法拋出的異常類型

例如:

//定義切入點,設定切入點表達式,方法名是切入點名稱
@Pointcut(value="execution(* cn.sjxy.Service.ProductService.*(..))")
@Pointcut(value="execution(* cn.sjxy.Service.ProductService.addProduct(..))")

4、AspectJ框架的使用 - 註解

1、pom.xml引入依賴包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.sjxy</groupId>
  <artifactId>chapter02Maven</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <dependencies>
  
  	<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
  	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
    	<version>5.3.0</version>
	</dependency>
	
	<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aop</artifactId>
    	<version>5.3.0</version>
	</dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aspects</artifactId>
    	<version>5.3.0</version>
	</dependency>
	
  </dependencies>
</project>

2、applicationContext.xml 開啓AspectJ註解使用方式

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop            
           http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

	<!-- 開啓掃包 -->
    <context:component-scan base-package="cn.sjxy"/>
	
	<!-- 開啓AspectJ 註解 -->
    <aop:aspectj-autoproxy />
    
</beans>

3、業務類代碼

@Service(value = "productService")
public class ProductService {
	
	public void addProduct() {
		System.out.println(">>>添加商品");
//		int a=1,b=0,c;
//		c=a/b;
	}
	
	public String findProduct()
	{
		System.out.println(">>>查看商品");
		return "SSM框架";
	}
	
	public void modifyProduct()
	{
		System.out.println(">>>修改商品");
	}
	
	public void deleteProduct()
	{
		System.out.println(">>>刪除商品");
	}
}

4、切面類代碼

@Component
@Aspect
public class MyAnnotationAspect {
	
	//定義切入點,設定切入點表達式,方法名是切入點名稱
	@Pointcut(value="execution(* cn.sjxy.Service.ProductService.addProduct(..))")
	private void myPointCut() {}
	
	//前置通知
	@Before(value="myPointCut()")
	public void beforeAdvice(JoinPoint jp)
	{
		System.out.println("2前置通知");
		System.out.println("被通知的方法名:"+jp.getSignature().getName());
	}
	
	//後置返回通知,能夠獲取到方法的返回值,有異常,則不執行
	@AfterReturning(value="myPointCut()",returning = "obj")
	public void afterReturningAdvice(JoinPoint jp,Object obj)
	{
		System.out.println("3後置返回通知");
		System.out.println("被通知的方法名:"+jp.getSignature().getName());
		System.out.println("方法返回結果:"+obj);
	}
	
	//環繞通知,在方法的前邊和後邊執行,有異常,則後邊不再執行
	@Around(value="myPointCut()")
	public Object roundAdvice(ProceedingJoinPoint pjp) throws Throwable{

		System.out.println("1=======begin========");
		Object resultValue = pjp.proceed();
		System.out.println("6=======end========");
		return resultValue;
	}
	
	//異常通知,產生異常時執行
	@AfterThrowing(pointcut="myPointCut()",throwing="ex")
	public void exceptionAdvice(Throwable ex)
	{
		System.out.println("4異常通知:程序的運行異常爲:"+ex.getMessage());
	}
	
	//最終通知,有異常也執行
	@After("myPointCut()")
	public void afterAdvice()
	{
		System.out.println("5最終通知,產生異常也執行");
	}
}

5、測試類代碼:

public class SpringTest {
	public static void main(String[] args)
	{
		 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
         
		 ProductService s = (ProductService)context.getBean("productService");
		 s.addProduct();	 
	}
}

6、執行結果截圖 - 無異常

7、執行結果截圖 - 有異常

 

3和6的通知不會被執行到。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章