一、背景
在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()方法进行了前置处理,与预期一致。