@[TOC]
系列文档索引
SpringAOP从入门到源码分析大全(一)熟悉动态代理 SpringAOP从入门到源码分析大全(二)熟悉ProxyFactory SpringAOP从入门到源码分析大全(三)ProxyFactory源码分析 SpringAOP从入门到源码分析大全(四)SpringAOP的源码分析 SpringAOP从入门到源码分析大全(五)手写一个编程式AOP
一、基于注解的AOP实现
日常我们开发中,通常都会使用基于注解的AOP实现。
此处就不多进行介绍了,相信咱们都会用。
但是要注意一点的,使用基于注解的AOP,必须要手动加上@EnableAspectJAutoProxy
这个注解,开启注解AOP,并且要使用注解AOP的话,需要引入AOP的包。
二、基于编程实现的AOP
基于编程实现的AOP,相比较而言轻量的多。
1、自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
2、定义拦截器
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* 这是一个Advice
*/
public class MyIntercepter implements MethodInterceptor {
/**
* 这相当于around通知
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result;
try {
System.out.println("前置通知");
result = invocation.proceed();
System.out.println("后置通知");
return result;
} catch (Exception e) {
System.out.println("异常通知");
throw e;
} finally {
System.out.println("最终通知");
}
}
}
3、定义Advisor
import org.aopalliance.aop.Advice;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.StaticMethodMatcher;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 这是一个Advisor
*/
public class MyAdvisor extends AbstractPointcutAdvisor {
// advice
private final Advice advice;
// 切点
private final Pointcut pointcut;
// 注解
private final Class<? extends Annotation> annotation;
public MyAdvisor(Advice advice, Class<? extends Annotation> annotation) {
this.advice = advice;
this.annotation = annotation;
this.pointcut = buildPointcut();
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
private Pointcut buildPointcut() {
Pointcut cpc = new AnnotationMatchingPointcut(annotation, true);
// 多个切点可以联合
Pointcut mpc = new AnnotationMethodPoint(annotation);
return new ComposablePointcut(cpc).union(mpc);
}
/**
* In order to be compatible with the spring lower than 5.0
*/
private static class AnnotationMethodPoint implements Pointcut {
private final Class<? extends Annotation> annotationType;
public AnnotationMethodPoint(Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "Annotation type must not be null");
this.annotationType = annotationType;
}
@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}
@Override
public MethodMatcher getMethodMatcher() {
return new AnnotationMethodMatcher(annotationType);
}
private static class AnnotationMethodMatcher extends StaticMethodMatcher {
private final Class<? extends Annotation> annotationType;
public AnnotationMethodMatcher(Class<? extends Annotation> annotationType) {
this.annotationType = annotationType;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (matchesMethod(method)) {
return true;
}
// Proxy classes never have annotations on their redeclared methods.
if (Proxy.isProxyClass(targetClass)) {
return false;
}
// The method may be on an interface, so let's check on the target class as well.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
return (specificMethod != method && matchesMethod(specificMethod));
}
private boolean matchesMethod(Method method) {
return AnnotatedElementUtils.hasAnnotation(method, this.annotationType);
}
}
}
}
4、配置类
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAOPConfig {
// 注意,这里一般通过spring.factory文件进行配置,保证AbstractAutoProxyCreator不冲突
@Bean
@ConditionalOnMissingBean(AbstractAutoProxyCreator.class)
public AbstractAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
}
@Bean
public Advisor myAdvisor(){
// 为Advisor加入拦截器与注解
MyAdvisor myAdvisor = new MyAdvisor(new MyIntercepter(), MyAnnotation.class);
return myAdvisor;
}
}
5、测试
@GetMapping("/testa")
public String testa() {
return "success";
}
@MyAnnotation
@GetMapping("/testb")
public String testb() {
return "success";
}
相关内容