基於Spring-AOP的APIs進行的切面編程示例

一、背景

在Spring的官方文檔裏,其中《Spring AOP APIs》一章裏講述了使用Spring-AOP的API進行切面編程的方法。地址如下:

https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/core.html#aop-api

於是簡單寫了個DEMO以加深鞏固;

二、說明

使用Spring-AOP的API進行切面編程與使用註解(@EnableAspectJAutoProxy+@Aspect+@Pointcut+@Around)的思路類似,大致步驟如下:

(1)定義Pointcut切入點;

(2)定義Advice通知

三、示例

Pointcut切入點的配置:接口EmailService的實現類中帶有@MyAnn註解的方法;

Advice通知的配置:使用BeforeAdvice前置通知進行攔截處理;

import java.lang.reflect.Method;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD })
@interface MyAnn {
}

interface EmailService {

	public String send(String s);
	
	@MyAnn
	public void test();
}

class MyEmailServiceImpl implements EmailService {

	@Override
	public String send(String s) {
		System.out.println("send message :" + s);
		return "ok";
	}

	@MyAnn
	@Override
	public void test() {
		System.out.println("this test function()" );
	}
}


public class Application {

	public static void main(String[] args) {

		// 構造切面的切入點Pointcut
		Pointcut myPointcut = new StaticMethodMatcherPointcut() {

			//切入點爲:EmailService的實現類中,標記有@MyAnn註解的方法
			@Override
			public boolean matches(Method method, Class<?> targetClass) {
				if (targetClass.isAssignableFrom(EmailService.class) || method.isAnnotationPresent(MyAnn.class)) {
					return true;
				}

				return false;
			}
		};

		// 設置前置通知方式處理
		BeforeAdvice myBeforeAdvice = new MethodBeforeAdvice() {

			@Override
			public void before(Method method, Object[] args, Object target) throws Throwable {
				System.out.println("!!!!!!!!before advice :" + method.getName());
			}

		};
		
		PointcutAdvisor myAdvisor = new DefaultPointcutAdvisor(myPointcut, myBeforeAdvice);
		
		ProxyFactory factory = new ProxyFactory(new MyEmailServiceImpl());
		factory.addAdvisor(myAdvisor);
		EmailService service = (EmailService) factory.getProxy();
		service.send("xxxx");
		service.test();
	}

}

運行結果:

send message :xxxx
!!!!!!!!before advice :test
this test function()

從結果中可以看出:

MyEmailServiceImpl的兩個方法中,只有test()方法進行了前置處理,與預期一致。

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