spring-aop-@Aspect詳細用法

@AspectJ的詳細用法 
在Spring AOP中目前只有執行方法這一個連接點,Spring AOP支持的AspectJ切入點指示符如下:

一些常見的切入點的例子 
execution(public * * (. .)) 任意公共方法被執行時,執行切入點函數。 
execution( * set* (. .)) 任何以一個“set”開始的方法被執行時,執行切入點函數。 
execution( * com.demo.service.AccountService.* (. .)) 當接口AccountService 中的任意方法被執行時,執行切入點函數。 
execution( * com.demo.service.. (. .)) 當service 包中的任意方法被執行時,執行切入點函數。 

within(com.demo.service.) 在service 包裏的任意連接點。 

within(com.demo.service. .) 在service 包或子包的任意連接點。 

this(com.demo.service.AccountService) 實現了AccountService 接口的代理對象的任意連接點。 
target(com.demo.service.AccountService) 實現了AccountService 接口的目標對象的任意連接點。 
args(java.io.Serializable) 任何一個只接受一個參數,且在運行時傳入參數實現了 Serializable 接口的連接點 
增強的方式: 
@Before:方法前執行 
@AfterReturning:運行方法後執行 
@AfterThrowing:Throw後執行 
@After:無論方法以何種方式結束,都會執行(類似於finally) 
@Around:環繞執行

添加 PointCut

該pointcut用來攔截test包下的所有類中的所有方法。

package com.aop.test1;

import org.aspectj.lang.annotation.Pointcut;

public class PointCuts {
	@Pointcut(value = "within(com.aop.test1.*)")
	public void aopDemo() {

	}
}

添加Aspect

該類中的advice將會用到上面的pointcut,使用方法請看各個advice的value屬性。

package com.aop.test1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class Aspect1 {

	@Before(value = "test.PointCuts.aopDemo()")
	public void before(JoinPoint joinPoint) {
		System.out.println("[Aspect1] before advise");
	}

	@Around(value = "test.PointCuts.aopDemo()")
	public void around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("[Aspect1] around advise 1");
		pjp.proceed();
		System.out.println("[Aspect1] around advise2");
	}

	@AfterReturning(value = "test.PointCuts.aopDemo()")
	public void afterReturning(JoinPoint joinPoint) {
		System.out.println("[Aspect1] afterReturning advise");
	}

	@AfterThrowing(value = "test.PointCuts.aopDemo()")
	public void afterThrowing(JoinPoint joinPoint) {
		System.out.println("[Aspect1] afterThrowing advise");
	}

	@After(value = "test.PointCuts.aopDemo()")
	public void after(JoinPoint joinPoint) {
		System.out.println("[Aspect1] after advise");
	}
}

添加測試用Controller

添加一個用於測試的controller,這個controller中只有一個方法,但是它會根據參數值的不同,會作出不同的處理:一種是正常返回一個對象,一種是拋出異常(因爲我們要測試@AfterThrowing這個advice)

package com.aop.test1;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/aop")
public class AopTestController {

	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(value = "/test", method = RequestMethod.GET)
	public Result test(@RequestParam boolean throwException) {
		// case 1
		if (throwException) {
			System.out.println("throw an exception");
			throw new RuntimeException("mock a server exception");
		}

		// case 2
		System.out.println("test OK");
		return new Result() {
			{
				this.setId(111);
				this.setName("mock a Result");
			}
		};
	}

	public static class Result {
		private int id;
		private String name;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
	}
}

我們會看到輸出的結果是:

[Aspect1] around advise 1
[Aspect1] before advisetest OK
[Aspect1] around advise2
[Aspect1] after advise
[Aspect1] afterReturning advise

異常情況,我們會看到輸出的結果是:

[Aspect1] around advise 1
[Aspect1] before advise
throw an exception
[Aspect1] after advise
[Aspect1] afterThrowing advise


正常情況: 
one-ok




異常情況: 
one-exception

@Component
@Aspect
public class CacheAspect {
    @Around("execution(public * *(..)) and @annotation(checkCache)")
    public Object get(ProceedingJoinPoint jp, CheckCache checkCache) throws Throwable {
    
    }
    @AfterReturning(pointcut = "@annotation(evictCache)", returning = "retval")
    public void remove(JoinPoint jp, EvictCache evictCache, Object retval) {
    
    }
}


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