扬州网站建设多少钱,做服装设计兼职的网站,Wordpress找不到外观选项,ui界面图标目录 1 AOP是什么2 AOP概念3 Springboot中使用AOP4 AOP原理5 应用场景 1 AOP是什么
AOP#xff08;Aspect Oriented Programming#xff09;意为#xff1a;面向切面编程#xff0c;通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续… 目录 1 AOP是什么2 AOP概念3 Springboot中使用AOP4 AOP原理5 应用场景 1 AOP是什么
AOPAspect Oriented Programming意为面向切面编程通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续是软件开发中的一个热点也是Spring框架中的一个重要内容是函数式编程的一种衍生范型。
利用AOP可对业务逻辑进行增强在不改变原有逻辑的基础上在其前后进行处理。降低了耦合性减少了大量冗余的操作。特别适合用于大量方法都需要进行相同处理的操作。
2 AOP概念
AOP是做了个切面在不破坏原有方法的基础上将切面切进去在其前后进行处理整体逻辑关系图如下
切面Aspect一般是指被Aspect修饰的类代表着某一具体功能的AOP逻辑。切入点Pointcut选择对哪些方法进行增强。通知Advice对目标方法的增强有一下五种增强的类型。 环绕通知Around内部执行方法可自定义在方法执行的前后操作。前置通知Before在方法执行前执行。后置通知After在方法执行后执行。返回通知AfterReturning在方法返回后执行。异常通知AfterThrowing在方法抛出异常后执行。 连接点JoinPoint就是那些被切入点选中的方法。这些方法会被增强处理。
对于各种通知的方法、注解等没有什么特别的操作具体使用会在后面举例。而切入点是选择对哪些方法生效的定义那怎么知道它选择的是哪些方法呢因为有多种匹配方式。
表达式类型功能execution()匹配方法最全的一个args()匹配入参类型args()匹配入参类型上的注解annotation()匹配方法上的注解within()匹配类路径within()匹配类上的注解this()匹配类路径实际上AOP代理的类target()匹配类路径目标类target()匹配类上的注解
用的比较多的是execution()和annotation execution(修饰符 返回值类型 方法名参数异常) 语法参数描述修饰符可选如publicprotected写在返回值前任意修饰符填*号就可以返回值类型必选可以使用*来代表任意返回值方法名必选可以用*来代表任意方法参数()代表是没有参数(…)代表是匹配任意数量任意类型的参数当然也可以指定类型的参数进行匹配如要接受一个String类型的参数则(java.lang.String), 任意数量的String类型参数(java.lang.String…)异常可选语法throws 异常异常是完整带包名可以是多个用逗号分隔看几个常用的写法 // 所有方法
execution(* *..*(..))
// 指定参数即入参本身的类型不能放其接口、父类
execution(* *..*(java.lang.String, java.lang.String)
// 指定方法前缀
execution(* *..*.prefix*(..))
// 指定方法后缀
execution(* *..*.*suffix(..))
// 组合增强所有方法但是去掉指定前缀和指定后缀的方法
execution(* *..*(..)) (!execution(* *..prefix*(..)) || !execution(* *..*suffix(..)))annotation() 匹配方法上的注解括号内写注解定义的全路径所有加了此注解的方法都会被增强。 // 增强被指定注解修饰的方法所有加了TestAspect注解的都会被
annotation(com.banmoon.test.annotation.TestAspect)
// 指定前缀的注解修饰的方法
annotation(com.banmoon.test.annotation.Prefix*)
// 指定后缀的注解修饰的方法
annotation(com.banmoon.test.annotation.*Suffix)3 Springboot中使用AOP 引入依赖 其实主要起作用的依赖是第二个但现在spring-boot-starter-web启动依赖中已经包含AOP依赖所以只引入第一个也可。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId
/dependency
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId
/dependency定义一个注解 import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Retention(RetentionPolicy.RUNTIME)
Target(ElementType.METHOD)
public interface Auth {}创建一个切面类 import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;Aspect
Component
public class AuthAspect {/*** 定义了一个切点* 这里的路径填自定义注解的全路径*/Pointcut(annotation(com.zz.business.annotations.Auth))public void authCut() {}Before(authCut())public void cutProcess(JoinPoint joinPoint) {MethodSignature signature (MethodSignature) joinPoint.getSignature();Method method signature.getMethod();System.out.println(注解方式AOP开始拦截, 当前拦截的方法名: method.getName());}After(authCut())public void after(JoinPoint joinPoint) {MethodSignature signature (MethodSignature) joinPoint.getSignature();Method method signature.getMethod();System.out.println(注解方式AOP执行的方法 : method.getName() 执行完了);}Around(authCut())public Object testCutAround(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println(注解方式AOP拦截开始进入环绕通知.......);Object proceed joinPoint.proceed();System.out.println(准备退出环绕......);return proceed;}/*** returning属性指定连接点方法返回的结果放置在result变量中** param joinPoint 连接点* param result 返回结果*/AfterReturning(value authCut(), returning result)public void afterReturn(JoinPoint joinPoint, Object result) {MethodSignature signature (MethodSignature) joinPoint.getSignature();Method method signature.getMethod();System.out.println(注解方式AOP拦截的方法执行成功, 进入返回通知拦截, 方法名为: method.getName() , 返回结果为: result.toString());}AfterThrowing(value authCut(), throwing e)public void afterThrow(JoinPoint joinPoint, Exception e) {MethodSignature signature (MethodSignature) joinPoint.getSignature();Method method signature.getMethod();System.out.println(注解方式AOP进入方法异常拦截, 方法名为: method.getName() , 异常信息为: e.getMessage());}
}可以看到先是定义了一个切点authCut之后前置通知、后置通知、环绕通知等都是绑在这个切点上在通过切点和指定方法连接起来。 连接点方法 该方法加了上面自定义的注解Auth RestController
RequestMapping(/company)
RefreshScope
public class CompanyController { GetMapping(/aopTest)Authpublic AjaxResult aopTest(RequestParam String name){//远程调用System.out.println(正在执行接口name name);return AjaxResult.success(执行成功 name);}
}执行后的流程如下图
可以看到环绕通知是包在最外侧的。
4 AOP原理
AOP的代理使用 JDK 动态代理和 CGLIB 代理来实现默认如果目标对象是接口则使用 JDK 动态代理否则使用 CGLIB 来生成代理类。
动态代理程序执行过程中使用JDK的反射机制创建代理类对象并动态的指定要代理目标类。动态代理涉及到的三个类 InvocationHandler接口处理器负责完调用目标方法就是被代理类中的方法并增强功能通过代理类对象执行目标接口中的方法会把方法的调用分派给调用处理器InvocationHandler的实现类执行实现类中的invoke()方法我们需要把在该invoke()方法中实现调用目标类的目标方法 Proxy 类通过 JDK 的 java.lang.reflect.Proxy 类实现动态代理 使用其静态方法 newProxyInstance()依据目标对象被代理类的对象、业务接口及调用处理器三者自动生成一个动态代理对象。 Method 类Method 是实例化的对象有一个方法叫 invoke()该方法在反射中就是用来执行反射对象的方法的。
在上述代码中也可以看到就是拿到了Method类型的对象可以调用invoke()方法执行除此之外还可以获取方法的各种属性getAnnotation-获取注解、getName()-方法名字等等。
5 应用场景
AOP在项目中通常用作一些共通的工作
接口方法日志的收集接口方法的权限校验前后对出入参的修改先查缓存这种需求