AspectJ

Aspectj与Spring AOP比较

img

XML配置方式

  • <aop:aspect>:  定义切面, 包括通知和切点. 是一般的bean
    
    //定义切面
    public class SleepHelperAspect{public void beforeSleep(){System.out.println("睡觉前要脱衣服!");}public void afterSleep(){System.out.println("起床后要穿衣服!");}
    }
    
    <bean id="sleepHelperAspect" class="com.ghs.aop.SleepHelperAspect"></bean><aop:aspectj-autoproxy/><aop:config><aop:pointcut expression="execution(* *.sleep(..))" id="sleepPointcut"/><aop:aspect ref="sleepHelperAspect"><!--前置通知--><aop:before method="beforeSleep" pointcut-ref="sleepPointcut"/><!--后置通知--><aop:after method="afterSleep" pointcut-ref="sleepPointcut"/></aop:aspect></aop:config>
    
  • <aop:advisor>  定义通知器, 跟切面一样,也包括通知(advice)和切点(PointCut) . 通知必须实现Advice接口.
    
    //定义通知
    public class SleepHelper implements MethodBeforeAdvice,AfterReturningAdvice{@Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {System.out.println("睡觉前要脱衣服!");}@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {System.out.println("起床后要穿衣服!");}
    }
    
    <bean id="sleepHelper" class="com.noob.aop.SleepHelper"></bean><aop:aspectj-autoproxy/>
    <aop:config><aop:pointcut expression="execution(* *.sleep(..))" id="sleepPointcut"/><aop:advisor advice-ref="sleepHelper" pointcut-ref="sleepPointcut"/>
    </aop:config>
    

基本概念

  1. Advice(通知、切面): 某个连接点所采用的处理逻辑,也就是向连接点注入的代码, AOP在特定的切入点上执行的增强处理。
  2. JointPoint(连接点):程序运行中的某个阶段点,比如方法的调用、异常的抛出等。
  3. Pointcut(切入点): JoinPoint的集合,是程序中需要注入Advice的位置的集合,指明Advice要在什么样的条件下才能被触发,在程序中主要体现为书写切入点表达式。
  4. Advisor(增强): **PointCut 和 Advice的综合体,**完整描述了一个advice将会在pointcut所定义的位置被触发。
  5. @Aspect(切面): 通常是一个类的注解,类中可以定义切入点和通知
  6. AOP Proxy:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类。

Pointcut

表示式(expression)和签名(signature)

//Pointcut表示式
@Pointcut("execution(* com.savage.aop.MessageSender.*(..))")
//Point签名
private void log(){} 

由下列方式来定义或者通过 &&、 ||、 !、 的方式进行组合:

  • execution:匹配 方法执行的连接点;
  • within: 目标对象target的类型是否和within中指定的类型匹配 。参数可指定包路径或具体的类全路径名。
    匹配原则:target.getClass().equals(within表达式中指定的类型)
  • this(类型全限定名): 通过aop创建的代理对象的类型是否和this中指定的类型匹配;注意判断的目标是代理对象;this中使用的表达式必须是类型全限定名,不支持通配符。
    匹配原则:this(x),则代理对象proxy满足下面条件时会匹配: x.getClass().isAssignableFrom(proxy.getClass());
  • target(类型全限定名): 判断目标对象的类型是否和指定的类型匹配;注意判断的目标是实际对象的类型;表达式必须是类型全限定名,不支持通配符。
    匹配原则: target(x),则目标对象target满足下面条件时会匹配 x.getClass().isAssignableFrom(target.getClass());
  • args:匹配 当前执行的方法传入的参数为指定类型的执行方法;
  • @within:自定义注解标注在类上,该类的所有方法(不包含子类方法)执行aop方法
  • @target:匹配 当前目标对象类型的执行方法,其中目标对象类持有指定的注解;
  • @args: 当前执行的方法传入的参数持有指定注解;
  • @annotation:匹配 执行方法持有指定注解;

格式

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)   其中后面跟着“?”的是可选项

括号中各个pattern分别表示:

  • 修饰符匹配(modifier-pattern?)
  • 返回值匹配(ret-type-pattern): 可以为*表示任何返回值, 全路径的类名等
  • 类路径匹配(declaring-type-pattern?)
  • 方法名匹配(name-pattern):可以指定方法名 或者 代表所有, set 代表以set开头的所有方法
  • 参数匹配((param-pattern)):可以指定具体的参数类型。多个参数间用“,”隔开,各个参数也可以用"" 来表示匹配任意类型的参数,"…"表示零个或多个任意参数。
    eg. (String)表示匹配一个String参数的方法;(
    ,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型。
  • 异常类型匹配(throws-pattern?)
  • 任意公共方法的执行:execution(public * *(…))
  • 任何一个以“set”开始的方法的执行:execution(* set*(…))
  • AccountService 接口的任意方法的执行:execution(* com.xyz.service.AccountService.*(…))
  • 定义在service包里的任意方法的执行: execution(* com.xyz.service..(…))
  • 定义在service包和所有子包里的任意类的任意方法的执行:execution(* com.xyz.service….(…))
    第一个表示匹配任意的方法返回值, …(两个点)表示零个或多个,第一个…表示service包及其子包,第二个表示所有类, 第三个*表示所有方法,第二个…表示方法的任意参数个数
  • 定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:execution(* com.test.spring.aop.pointcutexp…JoinPointObjP2.*(…))")
  • pointcutexp包里的任意类: within(com.test.spring.aop.pointcutexp.*)
  • pointcutexp包和所有子包里的任意类:within(com.test.spring.aop.pointcutexp…*)
  • 实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类:this(com.test.spring.aop.pointcutexp.Intf)
    当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型
  • 带有@Transactional标注的所有类的任意方法:
    • @within(org.springframework.transaction.annotation.Transactional)
    • @target(org.springframework.transaction.annotation.Transactional)
  • 带有@Transactional标注的任意方法:@annotation(org.springframework.transaction.annotation.Transactional)
    @within和@target针对类的注解,@annotation是针对方法的注解
  • 参数带有@Transactional标注的方法:@args(org.springframework.transaction.annotation.Transactional)
  • 参数为String类型(运行是决定)的方法: args(String)

JoinPoint

img

  1. @Before**AspectJMethodBeforeAdvice**标识一个前置增强方法.
  2. @After**AspectJAfterAdvice**f**inal**增强**,不管是抛出异常或者正常退出都会执行.
  3. @AfterReturning: **AspectJAfterReturningAdvice**后置增强,方法正常退出时执行.
  4. @AfterThrowing: **AspectJAfterThrowingAdvice**异常抛出增强.
  5. @Around: **AspectJAroundAdvice**环绕增强.

常用的方法:

  • Object[] getArgs:返回目标方法的参数
  • Signature getSignature():返回目标方法的签名信息。可获取方法名等
  • Object getTarget():返回被织入增强处理的目标对象
  • Object getThis():返回AOP框架为目标对象生成的代理对象

使用**@Around处理时,需要将第一个JoinPoint参数定义为ProceedingJoinPoint类型才可使用方法proceed

因为在org.springframework.aop.aspectj.AbstractAspectJAdvice 里默认supportsProceedingJoinPoint()为false; 而AspectJAroundAdvice重写为true;

Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around adviceat org.springframework.aop.aspectj.AbstractAspectJAdvice.maybeBindProceedingJoinPoint(AbstractAspectJAdvice.java:414) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.AbstractAspectJAdvice.calculateArgumentBindings(AbstractAspectJAdvice.java:388) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvice(ReflectiveAspectJAdvisorFactory.java:294) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice(InstantiationModelAwarePointcutAdvisorImpl.java:149) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.<init>(InstantiationModelAwarePointcutAdvisorImpl.java:113) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor(ReflectiveAspectJAdvisorFactory.java:198) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors(ReflectiveAspectJAdvisorFactory.java:126) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors(BeanFactoryAspectJAdvisorsBuilder.java:110) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:95) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:101) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:251) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:1124) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:1097) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:504) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]... 15 common frames omitted

img

spring-core模块中: 提供支持cgliborg.springframework.cglib.proxy.MethodInterceptor是给 org.springframework.cglib.proxy.Enhancer使用的 org.springframework.cglib.proxy.Callback

public interface MethodInterceptor extends Callback {Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}

spring-aop模块中:org.aopalliance.intercept.MethodInterceptor根本上是一个org.aopalliance.aop.Advice

public interface MethodInterceptor extends Interceptor {Object invoke(MethodInvocation invocation) throws Throwable;
}public interface Interceptor extends Advice {}

织入

     @AfterReturning(pointcut="execution(* com.abc.service.*.access*(..)) && args(time, name)",returning="returnValue")public void invoke(Date time, Object returnValue, String name) {System.out.println("目标方法中的参数String = " + name);System.out.println("目标方法中的参数Date = " + time);System.out.println("目标方法的返回结果returnValue = " + returnValue);}

表达式中增加了args(time, name)部分,意味着可以在增强处理的签名方法(access方法)中定义"time"和"name"两个同名属性。这两个形参的类型由access方法同名参数类型指定。一旦指定了, 则这两个形参类型将用于限制该切入点只匹配第一个参数类型为Date,第二个参数类型为String的方法(方法参数个数和类型若有不同均不匹配);
access方法只需要满足"time", "name"参数的顺序和pointcut中args(time, name)的顺序相同即可,"returnValue"位置顺序无所谓。

eg.

//将被access方法匹配
public String accessAdvice(Date d, String n) {System.out.println("方法:accessAdvice");return "aa";
}

img

执行顺序

package com.noob.controller.Interceptor;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class AdviceInterceptor {@Pointcut(value = "execution(public String com.noob.controller.BService.testAdvice(..))")public void pointcut() {}@Before("pointcut()")public void before(JoinPoint point) {System.out.println("before");}@Around("pointcut()")public Object around(ProceedingJoinPoint point) throws Throwable {System.out.println("around begin");try {Object proceed = point.proceed();System.out.println("around after");return proceed;} catch (Throwable e) {System.out.println("around after exception");throw e;}}@After("pointcut()")public void after() throws Throwable {System.out.println("after");}@AfterReturning("pointcut()")public void afterReturning() throws Throwable {System.out.println("afterReturning");}@AfterThrowing("pointcut()")public void afterThrowing() {System.out.println("afterThrowing");}
}---@Component
public class BService {public String testAdvice() {System.out.println("目标方法testAdvice");throw new RuntimeException("fail");// return "testAdvice";}
}

正常情况执行结果:

around begin
before
目标方法testAdvice
around after
after
afterReturning

one-ok

有异常情况下:

around begin
before
目标方法testAdvice
around after exception
after
afterThrowing

one-exception

测试过程中发现,debug模式下可知JoinPoint的实际类型是org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint(before、around 都是该实际类型)

img

但若代码直接写定该类型,启动报错

Caused by: java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:319) ~[aspectjweaver-1.9.4.jar:na]at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:227) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.AspectJExpressionPointcut.obtainPointcutExpression(AspectJExpressionPointcut.java:198) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:177) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:225) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:288) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:320) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:126) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:95) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:76) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:347) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:429) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]

因为, 执行到ReflectiveAspectJAdvisorFactory.getAdvisors -> ReflectiveAspectJAdvisorFactory.getAdvice -> AbstractAspectJAdvice.calculateArgumentBindings()时:对JoinPoint.classProceedingJoinPoint.class是不用额外处理参数绑定。

img

所以MethodInvocationProceedingJoinPoint被当作额外的参数。

后续先执行进入org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression -> PointcutParser.resolvePointcutExpression:

PointcutParser.buildResolutionScope创建参数类型绑定关系。

img

接着执行进入org.aspectj.weaver.patterns.Pointcut.resolve:

首先 Pointcut.resolveBindings来根据实际情况解析该绑定关系; 接着执行校验方法Bindings.checkAllBound因真实绑定为空,判定失败后异常

img

同一个方法被多个Aspect类拦截

优先级高的切面类里的增强处理 优先于 优先级低的切面类。

在“进入”连接点时,最高优先级的增强处理将先被织入(eg. 给定的两个不同切面类Before增强处理中,优先级高的那个会先执行);

在“退出”连接点时,最高优先级的增强处理会最后被织入(eg. 给定的两个不同切面类After增强处理中,优先级高的那个会后执行)。

eg. 优先级为1的切面类Bean1包含了@Before,优先级为2的切面类Bean2包含了@Around,虽然@Around优先级高于@Before,但由于Bean1的优先级高于Bean2的优先级,因此Bean1中的@Before先被织入。

Spring提供了如下两种解决方案指定不同切面类里的增强处理的优先级:

  1. 让切面类实现org.springframework.core.Ordered接口:实现该接口的int getOrder()方法,该方法返回值越小,优先级越高
  2. 直接使用@Order注解来修饰一个切面类:使用这个注解时可以配置一个int类型的value属性,该属性值越小,优先级越高

同一个切面类里的两个相同类型的增强处理在同一个连接点被织入时,Spring AOP将以随机的顺序来织入这两个增强处理,没有办法指定它们的织入顺序。即使给这两个 advice 添加了 @Order 这个注解,也不行!

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

aixs1 生成java代码_通过axis1.4 来生成java客户端代码

1.首先下载axis-1.4所有的jar包&#xff0c;2.我是直接打开cmd&#xff0c;进入到该jar包的目录下&#xff0c;3.直接运行命令(运行这个命令之前要确定java的环境变量都已配置好)&#xff1a;java -Djava.ext.dirs${lib的目录} org.apache.axis.wsdl.WSDL2Java -o${代码输出路径…

windows分屏_windows内到底藏了多少好东西?

恭喜!点开这篇文章&#xff0c;你将解锁 WIN10 系统内那些不为人知的高效的冷知识&#xff01;相信所有的职场人都会搜索过这样的问题&#xff1a;有哪些高效的办公神器&#xff1f;在之前的文章中&#xff0c;我分享过很多高效神器&#xff0c;如果你感兴趣的话&#xff0c;点…

@Aspect中@Pointcut 12种用法

本文主要内容&#xff1a;掌握Pointcut的12种用法。 Aop相关阅读 阅读本文之前&#xff0c;需要先掌握下面3篇文章内容&#xff0c;不然会比较吃力。 Spring系列第15篇&#xff1a;代理详解&#xff08;java动态代理&CGLIB代理)Spring系列第30篇&#xff1a;jdk动态代理…

asp.net接受表单验证格式后再提交数据_看滴普科技大前端如何玩转el-form-renderer 表单渲染器1.14.0

DEEPEXI 大前端常人道&#xff0c;一入开发深似海&#xff0c;技术学习无止境。在新技术层出不穷的前端开发领域&#xff0c;有一群身怀绝技的开发&#xff0c;他们在钻研前沿技术的同时&#xff0c;也不忘分享他们的成果&#xff0c;回馈社区。下面&#xff0c;就由小水滴带大…

测试用例设计方法_黑盒测试——测试用例设计方法

黑盒测试也称为功能测试或数据驱动测试。通过软件的外部表现来发现其缺陷和错误。在测试时&#xff0c;把被测程序视为一个不能打开的盒子&#xff0c;在完全不考虑程序内部逻辑结构和内部特性的情况下进行。它是在已知产品所应具有的功能前提下&#xff0c;通过测试来检测每个…

SpringAop @Pointcut(“@annotation“)\@Aspect练习

切面记录日志 切面类 Slf4j Aspect Component public class AspectForFeign {Pointcut("execution(public * com.keke.remote..*Feign.*(..))")public void pointcut() {}Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint) thro…

Mybatis缓存机制详解与实例分析

前言&#xff1a; 本篇文章主要讲解Mybatis缓存机制的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出&#xff0c;对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了&#x1f601; 以下正文开始 Mybat…

delphi语言转为汇编语言_每天5分钟,轻松建立技术图谱 编程语言黑历史

阿T课堂开播啦&#xff01;这里只有干货干锅&#xff0c;没有水坑没有套路&#xff01;计算机编程语言的发展&#xff0c;也是随着计算机本身发展而发展。人类不断的提高科技的同时&#xff0c;也必须使工具的使用越来越简化&#xff0c;从而提高整个社会效率&#xff0c;这其中…

水系图一般在哪里找得到_进展 | 水系钠离子电池研究取得重要进展

水系钠离子电池兼具钠资源储量丰富和水系电解液本质安全的双重优势被视为一种理想的大规模静态储能技术。此前&#xff0c;我们针对这水系钠离子电池体系做了一些探索(Nature Communications 2015, 6, 6401&#xff1b;Advanced Energy Materials 2015, 5, 1501005&#xff1b;…

@Around简单使用示例——SpringAOP增强处理

Around的作用 既可以在目标方法之前织入增强动作&#xff0c;也可以在执行目标方法之后织入增强动作&#xff1b;可以决定目标方法在什么时候执行&#xff0c;如何执行&#xff0c;甚至可以完全阻止目标目标方法的执行&#xff1b;可以改变执行目标方法的参数值&#xff0c;也…

python numpy逆_Python使用numpy计算矩阵特征值、特征向量与逆矩阵

原标题&#xff1a;Python使用numpy计算矩阵特征值、特征向量与逆矩阵 Python扩展库numpy.linalg的eig()函数可以用来计算矩阵的特征值与特征向量&#xff0c;而numpy.linalg.inv()函数用来计算可逆矩阵的逆矩阵。 >>> importnumpy as np >>> x np.matrix([…

Mysql索引数据结构有多个选择,为什么一定要是B+树呢?_面试 (MySQL 索引为啥要选择 B+ 树)

Mysql索引数据结构 下面列举了常见的数据结构 二叉树红黑树Hash表B-Tree&#xff08;B树&#xff09; Select * from t where t.col5我们在执行一条查询的Sql语句时候&#xff0c;在数据量比较大又不加索引的情况下&#xff0c;逐行查询并进行比对&#xff0c;每次需要从磁盘…

一篇搞懂mysql中的索引(大白话版)

容易来说&#xff0c;索引的出现其实就是为了提升数据查询的效率&#xff0c;就像书的目录一样。一本 500 页的书&#xff0c;如果你想快速找到其中的某一个知识点&#xff0c;在不借助目录的情况下&#xff0c;那我估计你可得找一会儿。同样&#xff0c;对于数据库的表而言&am…

sqlite插入时间字段_sqlite 获取最后插入id

(点击上方公众号&#xff0c;可快速关注)SQLite数据库中的表均有一个特殊的rowid字段&#xff0c;它是一个不重复的64位有符号整数&#xff0c;默认起始值为1。rowid别名为oid或_rowid_&#xff0c;但在创建表的SQL声明语句中只能使用rowid作为关键字。如果在创建表的时候设置了…

Dubbo与SpringCloud的架构与区别

Dubbo与SpringCloud的架构与区别 Dubbo架构图 SpringCloud 架构图 总结 框架DubboSpringCloud服务注册中心ZookeeperSpring Cloud Netfix Eureka(nacos)服务调用方式RPCREST API服务监控Dubbo-monitorSpring Boot Admin熔断器不完善Spring Cloud Netflix Hystrix服务网关无Sp…

matlab求微分数值,用MATLAB语言求微积分方程的数值解.(xd^2y)/dx^2-5dy/dx+y=0y(0)=0y'(0)=0...

function dymyfun03(x,y)dyzeros(3,1) %初始化变量dydy(1)y(2); %dy(1)表示y的一阶导数,其等于y的第二列值dy(2)5/x*y(3)-y(1); %dy(2)表示y的二阶导数%ex0808 用ode23 ode45 ode113解多阶微分方程clear,clc[x23,y23]ode23(myfun03,[1,10],[1 10 30]);[x45,y45]ode45(myfun03,[…

springboot 接口404_资深架构带你学习Springboot集成普罗米修斯

这篇文章主要介绍了springboot集成普罗米修斯(Prometheus)的方法&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧&#xff01;Prometheus 是一套开源的系统监控报警框…

http常见的状态码,400,401,403状态码分别代表什么?

2XX 成功 200 OK&#xff0c;表示从客户端发来的请求在服务器端被正确处理 204 No content&#xff0c;表示请求成功&#xff0c;但响应报文不含实体的主体部分 206 Partial Content&#xff0c;进行范围请求 3XX 重定向 301 moved permanently&#xff0c;永久性重定…

mysql left 数学原理,MySQL全面瓦解21(番外):一次深夜优化亿级数据分页的奇妙经历...

背景1月22号晚上10点半&#xff0c;下班后愉快的坐在在回家的地铁上&#xff0c;内心想着周末的生活怎么安排。sql忽然电话响了起来&#xff0c;一看是咱们的一个开发同窗&#xff0c;顿时紧张了起来&#xff0c;本周的版本已经发布过了&#xff0c;这时候打电话通常来讲是线上…

java8中的map与flatmap区别

map:只能返回一个值 flatmap:返回多个值 new ArrayList().stream().map(x -> x);//返回一个 new ArrayList().stream().flatMap(x -> Arrays.asList(x.split(" ")).stream());//返回一个流,也就是多个值 看API声明可以发现&#xff0c;flatmap接受的参数是流…