无锡定制网站,网站建设的运用场景,设计类平台网站,住房城乡建设局网站1.AOP基本介绍 AOP 的全称 (aspect oriented programming) #xff0c;面向切面编程。 1.和传统的面向对象不同。 面向切面编程是根据自我的需求#xff0c;将切面类的方法切入到其他的类的方法中。#xff08;这么说抽象吧#xff01;来张图来解释。#xff09; 如图 传…1.AOP基本介绍 AOP 的全称 (aspect oriented programming) 面向切面编程。 1.和传统的面向对象不同。 面向切面编程是根据自我的需求将切面类的方法切入到其他的类的方法中。这么说抽象吧来张图来解释。 如图 传统的面向对象方法是 对象.方法()然后被调用
面向切面编程是什么呢
首先满足 1 类的这个方法是通过动态代理实现的比如有个A.say()方法。 然后有一个切面类B这个类也有许多方法比如study()但是不同的是这个类中的方法study()可以插入到A.say()的方法前后进行。 当A.say()被调用的时候切面类B的study()方法就会被自动调用。 这就和传统的直接调用B.study()方法不同切面类的方法是直接插入到另外一个动态代理类的方法的前后的。 AOP的核心概念
面向切面编程AOP是一种编程范式它允许开发者将横切关注点如日志记录、事务管理、安全性等与业务逻辑分离从而提高代码的模块化和可维护性。在Java中AOP通常通过使用框架如Spring来实现。
介绍AOP的关键术语
切面Aspect切面是封装横切关注点的模块。它包含了一组通知Advice和切入点Pointcut。 连接点Joinpoint在程序执行过程中的特定点如方法的调用或执行异常的抛出等。 切点Pointcut切点是定义在哪些连接点上应用通知的规则。 通知Advice通知是在切点上执行的代码它定义了在连接点上执行的逻辑如前置、后置、环绕等。 解释AOP的几种通知类型
前置Before在方法执行前执行的通知。 后置After在方法执行后执行的通知无论方法是否成功执行。 环绕Around在方法调用前后都可以执行的通知可以控制方法的调用过程。 异常Throws在方法抛出异常后执行的通知。 最终AfterReturning在方法正常返回后执行的通知。 2.AOP的快速入门
在xml配置下 context:annotation-config/context:component-scan base-packageaspectj/!--启用基于注解方式的AOP功能--aop:aspectj-autoproxy proxy-target-classtrue/
【Spring进阶系列丨第十篇】基于注解的面向切面编程(AOP)详解_spring 切面 注解-CSDN博客
3.AOP的切入表达式
语法细节
注意第一个*是包含了任意的权限修饰符和返回值。 方法说明 注意细节 1. 切入表达式也可以指向类的方法 , 这时切入表达式会对该类 / 对象生效 2. 切入表达式也可以指向接口的方法 , 这时切入表达式会对实现了接口的类 / 对象生效 3. 切入表达式也可以对没有实现接口的类进行切入 (因为Spring的CGLIB)。 4.JoinPoint连接点 作用通过 JoinPoint 可以获取到调用方法的签名 signature 方法 // 获取目标方法名 joinPoint.getSignature().getName(); // 获取目标方法所属类的简单类名 joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的类名 joinPoint.getSignature().getDeclaringTypeName(); // 获取目标方法声明类型(public、private、protected) joinPoint.getSignature().getModifiers(); // 获取传入目标方法的参数返回一个数组 Object[] args joinPoint.getArgs(); // 获取被代理的对象 joinPoint.getTarget(); // 获取代理对象自己 joinPoint.getThis(); 在如下代码中要将beforeMethod()方法切入到aspectj包下的SmartDog类的getSum()下 Before(value execution(public float aspectj.SmartDog.getSum(float, float)))
public void beforeMethod(JoinPoint joinPoint){
joinPoint.getSignature().getName(); // 获取目标方法名
joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的简单类名
joinPoint.getSignature().getDeclaringTypeName(); // 获取目标方法所属类的类名
joinPoint.getSignature().getModifiers(); // 获取目标方法声明类型(public、private、protected)
Object[] args joinPoint.getArgs(); // 获取传入目标方法的参数返回一个数组
joinPoint.getTarget(); // 获取被代理的对象
joinPoint.getThis(); // 获取代理对象自己
} 5.返回异常环绕通知返回结果
//返回通知AfterReturning(value execution(public float aspectj.SmartDog.getSum(float, float)), returning res)public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature joinPoint.getSignature();System.out.println(SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名- signature.getName() 返回的结果是 res);}//异常通知AfterThrowing(value execution(public float aspectj.SmartDog.getSum(float, float)), throwing throwable)public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature joinPoint.getSignature();System.out.println(SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名- signature.getName() 异常信息 throwable);}6.切入点表达式重用
在这些切入方法里面如果是作用于同一个方法就会让切入表达式感到重复和冗余于是为了统一管理切入点表达式可以使用切入点表达式重用技术
package aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;/*** version 1.0* 这是一个切面类*/
Aspect
Component(smartAnimalAspect)
public class SmartAnimalAspect {// 切入表达式重用技术Pointcut(value execution(public float aspectj.SmartDog.getSum(float, float)))public void mypointcut(){}//给SmartDog配置前置返回异常最终通知//解读//1.Before表示我们目标对象执行前要执行的哪个方法//2.value execution(public float aspectj.SmartDog.getSum(float, float))// 是指定切入到哪个类的哪个方法 形式是:访问修饰符 返回类型 全类名.方法名(形参列表) execution是执行的意思// JoinPoint joinPoint 在底层执行的时候由Aspectj切面框架会给该切入方法传入jointPoint对象// 通过该对象可以获得相关的信息。//前置通知Before(value mypointcut())public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature joinPoint.getSignature();System.out.println(SmartAnimalAspect-切面类showBeginLog()[使用的myPointCut()]-方法执行前-日志-方法名- signature.getName() -参数 Arrays.asList(joinPoint.getArgs()));}//返回通知AfterReturning(value mypointcut(),returning res)public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature joinPoint.getSignature();System.out.println(SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名- signature.getName() 返回的结果是 res);}//异常通知AfterThrowing(value mypointcut(),throwing throwable)public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature joinPoint.getSignature();System.out.println(SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名- signature.getName() 异常信息 throwable);}//最终通知After(value mypointcut())public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature joinPoint.getSignature();System.out.println(SmartAnimalAspect-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名- signature.getName());}}7.切面优先级问题 ● 切面优先级问题 : 如果同一个方法有多个切面在同一个切入点切入那么执行的优先级如何控制 . ● 基本语法 order(valuen) 来控制 n 值越小优先级越高 . 举例 切面类1(优先执行)
package aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;/*** version 1.0* 这是一个切面类*/
Order(value 1)
Aspect
Component(smartAnimalAspect)
public class SmartAnimalAspect {// 切入表达式重用技术Pointcut(value execution(public float aspectj.SmartDog.getSum(float, float)))public void mypointcut(){}//前置通知
// Before(value execution(public float aspectj.SmartDog.getSum(float, float)))Before(value mypointcut())public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature joinPoint.getSignature();System.out.println(1前置通知 signature.getName() -参数 Arrays.asList(joinPoint.getArgs()));}//返回通知
// AfterReturning(value execution(public float aspectj.SmartDog.getSum(float, float)), returning res)AfterReturning(value mypointcut(),returning res)public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature joinPoint.getSignature();System.out.println(1返回通知 signature.getName() 返回的结果是 res);}//异常通知
// AfterThrowing(value execution(public float aspectj.SmartDog.getSum(float, float)), throwing throwable)AfterThrowing(value mypointcut(),throwing throwable)public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature joinPoint.getSignature();System.out.println(1异常通知 signature.getName() 异常信息 throwable);}//最终通知
// After(value execution(public float aspectj.SmartDog.getSum(float, float)))After(value mypointcut())public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature joinPoint.getSignature();System.out.println(1最终通知 signature.getName());}}切面类2(没有切面类1的优先级高)
package aspectj;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** version 1.0* 这是一个切面类*/
Order(value 2)
Aspect
Component(smartAnimalAspect2)
public class SmartAnimalAspect2 {// 切入表达式重用技术Pointcut(value execution(public float aspectj.SmartDog.getSum(float, float)))public void mypointcut(){}//前置通知
// Before(value execution(public float aspectj.SmartDog.getSum(float, float)))Before(value mypointcut())public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature joinPoint.getSignature();System.out.println(2前置通知);}//返回通知
// AfterReturning(value execution(public float aspectj.SmartDog.getSum(float, float)), returning res)AfterReturning(value mypointcut(),returning res)public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature joinPoint.getSignature();System.out.println( 2返回通知 返回的结果是 res);}//异常通知
// AfterThrowing(value execution(public float aspectj.SmartDog.getSum(float, float)), throwing throwable)AfterThrowing(value mypointcut(),throwing throwable)public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature joinPoint.getSignature();System.out.println(2异常通知 throwable);}//最终通知
// After(value execution(public float aspectj.SmartDog.getSum(float, float)))After(value mypointcut())public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature joinPoint.getSignature();System.out.println(2最终通知 signature.getName());}}结果 注意 不能理解成优先级高的每个消息通知都先执行这个和方法调用机制(和 Filter 过滤器 链式调用类似) 8.基于XML的AOP
定义SmartAnimalable接口
package xml;/*** author ygd*/
public interface SmartAnimalable {float getSum(float i, float j);float getSub(float i, float j);
}
定义SmartDog类
package xml;/*** author ygd*/
public class SmartDog implements SmartAnimalable {Overridepublic float getSum(float i, float j) {float result i j;System.out.println(getSum() 方法内部打印 result result);return result;}Overridepublic float getSub(float i, float j) {float result i - j;System.out.println(getSub() 方法内部打印 result result);return result;}
}
定义SmartAnimalAspect切面类
package xml;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;import java.util.Arrays;/*** version 1.0* 这是一个基于XML的切面类*/public class SmartAnimalAspect {public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature joinPoint.getSignature();System.out.println(1前置通知 signature.getName() -参数 Arrays.asList(joinPoint.getArgs()));}public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature joinPoint.getSignature();System.out.println(1返回通知 signature.getName() 返回的结果是 res);}public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature joinPoint.getSignature();System.out.println(1异常通知 signature.getName() 异常信息 throwable);}public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature joinPoint.getSignature();System.out.println(1最终通知 signature.getName());}}定义beans01.xml ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd!--配置一个切面类对象-bean--bean classxml.SmartAnimalAspect idsmartAnimalAspect/
!--配置SmartDog对象-bean--bean classxml.SmartDog iddog/
!--配置切面类一定要引入xmlns:aop命名空间--aop:config
!-- 注意顺序先配置切入点在配置切面对象--
!--配置切入点--aop:pointcut idmypointcut expressionexecution(public float xml.SmartDog.getSum(float, float))/
!--这里指定切面对象--aop:aspect refsmartAnimalAspect order10
!--配置前置通知--aop:before methodshowBeginLog pointcut-refmypointcut/
!--配置返回通知--aop:after-returning methodshowSuccessEndLog pointcut-refmypointcut returningres/
!--配置异常通知--aop:after-throwing methodshowExceptionLog pointcut-refmypointcut throwingthrowable/
!--配置最终通知--aop:after methodshowFinallyEndLog pointcut-refmypointcut//aop:aspect/aop:config/beans
注意点要 先配置切面点在配置切面类
xml的语法跟上面所写的基于注解的aop道理都是一样的。
9.Spring的AOP机制是基于Spring框架中的基于JDK的动态代理和基于CGLib的动态代理
动态代理 基于jdk的Proxy(面向接口) 与spring的CGlib(面向父类)-CSDN博客