1. 程式人生 > >Spring-Aop編程(AspectJ)(3)

Spring-Aop編程(AspectJ)(3)

功能 允許 ng- highlight tex service 手動 數據處理 方法的參數

AspectJ

1. 介紹

AspectJ是一個基於Java語言的AOP框架,Spring2.0以後新增了對AspectJ切點表達式支持,@AspectJ 是AspectJ1.5新增功能,通過JDK5註解技術,允許直接在Bean類中定義切面,它是一種新版本Spring框架,建議使用AspectJ方式來開發AOP。主要用途:自定義開發

2.切入點表達式

  為了能夠靈活定義切入點位置,Spring AOP提供了多種切入點指示符。

execution———用來匹配執行方法的連接點

  語法結構: execution( 方法修飾符 方法返回值 方法所屬類 匹配方法名 ( 方法中的形參表 ) 方法申明拋出的異常 )

  其中紅色字體的部分時不能省略的,各部分都支持通配符 “*” 來匹配全部

  比較特殊的為形參表部分,其支持兩種通配符

  •   "*":代表一個任意類型的參數;
  •   “..”:代表零個或多個任意類型的參數。

  例如:

    ()匹配一個無參方法

    (..)匹配一個可接受任意數量參數和類型的方法

    (*)匹配一個接受一個任意類型參數的方法

    (*,Integer)匹配一個接受兩個參數的方法,第一個可以為任意類型,第二個必須為Integer。

  下面舉一些execution的使用實例:

分類 示例 描述
通過方法簽名定義切入點 execution(public * * (..))
匹配所有目標類的public方法,第一個*為返回類型,第二個*為方法名
execution(* save* (..)) 匹配所有目標類以save開頭的方法,第一個*代表返回類型
execution(**product(*,String)) 匹配目標類所有以product結尾的方法,並且其方法的參數表第一個參數可為任意類型,第二個參數必須為String
通過類定義切入點 execution(* aop_part.Demo1.service.*(..)) 匹配service接口及其實現子類中的所有方法
通過包定義切入點 execution(* aop_part.*(..)) 匹配aop_part包下的所有類的所有方法,但不包括子包
execution(* aop_part..*(..)) 匹配aop_part包下的所有類的所有方法,包括子包。(當".."出現再類名中時,後面必須跟“*”,表示包、子孫包下的所有類)
execution(* aop_part..*.*service.find*(..)) 匹配aop_part包及其子包下的所有後綴名為service的類中,所有方法名必須以find為前綴的方法
通過方法形參定義切入點 execution(*foo(String,int)) 匹配所有方法名為foo,且有兩個參數,其中,第一個的類型為String,第二個的類型為int
execution(* foo(String,..)) 匹配所有方法名為foo,且至少含有一個參數,並且第一個參數為String的方法(後面可以有任意個類型不限的形參)

within————通過類匹配模式申明切入點(只能通過類型匹配連接點)

    例如:within(aop_part..*) 表示匹配包aop_part以及子包的所有方法

    由於execution可以匹配包、類、方法,而within只能匹配包、類,因此execution完全可以代替within的功能。


this————限定AOP代理必須時指定類型的實例,用於匹配該對象的所有連接點

    例如:this(aop_part.service.GodService) 表示匹配了GodService接口的代理對象的所有連接點


target————通過判斷目標類的類型確定判斷的是否匹配

    this通過判斷代理類的類型來決定是否和切入點匹配,兩者限定的對象都是指定類型的實例。

    例如: target(aop_part.service.GodService) 表示匹配實現了GodService接口的目標對象的所有連接點


args————用於對連接點的參數類型進行限制,要求參數類型時指定類型的實例

    例如:args(aop_part.service) 表示匹配時,出入的參數類型時service的方法

    其與execution(**(aop_part.service))的區別為,execution針對的時方法簽名,而args針對的是運行時的實際參數類型。

    args既匹配buyGoods(service newService),也匹配buyGoods(Buyservice newService) <Buyservice為service的子類>

    execution只匹配buyGoods(service newService)


組合切入點

    支持 &&、 || 、!

    與其他語言所代表的意思相同

    例:args(aop_part.service) &&execution(**(aop_part.service))

3.AspectJ 通知類型

aop聯盟定義通知類型,具有特性接口,必須實現,從而確定方法名稱。

aspectj 通知類型,只定義類型名稱。已經方法格式。

個數:6種,知道5種,掌握1中。

before:前置通知(應用:各種校驗)在方法執行前執行,如果通知拋出異常,阻止方法運行

afterReturning:後置通知(應用:常規數據處理)方法正常返回後執行,如果方法中拋出異常,通知無法執行必須在方法執行後才執行,所以可以獲得方法的返回值。

around:環繞通知(應用:十分強大,可以做任何事情)方法執行前後分別執行,可以阻止方法的執行必須手動執行目標方法

afterThrowing:拋出異常通知(應用:包裝異常信息)方法拋出異常後執行,如果方法沒有拋出異常,無法執行

after:最終通知(應用:清理現場) 方法執行完畢後執行,無論方法中是否出現異常

Spring Aop實例:

UserService.java

package com.zk.b_annotation;

public interface UserService {
	
	public void addUser();
	public String updateUser();
	public void deleteUser();

}

UserServiceImpl.java

package com.zk.b_annotation;

import org.springframework.stereotype.Service;

@Service("userServiceId")
public class UserServiceImpl implements UserService {

	@Override
	public void addUser() {
		System.out.println("d_aspect.b_anno addUser");
	}

	@Override
	public String updateUser() {
		System.out.println("d_aspect.b_anno updateUser");
		int i = 1/ 0;
		return "陽誌就是";
	}

	@Override
	public void deleteUser() {
		
		System.out.println("d_aspect.b_anno deleteUser");
	}
}

  

切面

MyAspect.java

package com.zk.b_annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面類,含有多個通知
 */
@Component
@Aspect
public class MyAspect {
	
	//前置通知
//	@Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")
	public void myBefore(JoinPoint joinPoint){
		System.out.println("前置通知" + joinPoint.getSignature().getName());
	}
	
	//聲明公共切入點
	@Pointcut("execution(* com.zk.b_annotation.UserServiceImpl.*(..))")
	private void myPointCut(){
	}
	
//	@AfterReturning(value="myPointCut()" ,returning="ret")
	public void myAfterReturning(JoinPoint joinPoint,Object ret){
		System.out.println("後置通知" + joinPoint.getSignature().getName() + " , -->" + ret);
	}
	
//	@Around(value = "myPointCut()")
	public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("前置通知");
		//手動執行目標方法
		Object obj = joinPoint.proceed();
		
		System.out.println("後置通知");
		return obj;
	}
	
//	@AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e")
	public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
		System.out.println("拋出異常通知" + e.getMessage());
	}
	
	@After("myPointCut()")
	public void myAfter(JoinPoint joinPoint){
		System.out.println("後置通知");
	}

}

  

beans.xml配置文件

<?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.xsd
       					   http://www.springframework.org/schema/aop 
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!-- 1.掃描 註解類 -->
	<context:component-scan base-package="com.zk.b_annotation"></context:component-scan>
	
	<!-- 2.確定 aop註解生效 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

  

TestAspectAnno.java

package com.zk.b_annotation;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAspectAnno {
	
	@Test
	public void demo01(){
		String xmlPath = "com/zk/b_annotation/beans.xml";
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		
		//獲得目標bean
		UserService userService = (UserService) applicationContext.getBean("userServiceId");
		userService.addUser();
		userService.updateUser();
		userService.deleteUser();
	}

}

  

運行效果圖:

技術分享圖片

技術分享圖片

Spring-Aop編程(AspectJ)(3)