@Aspect

AOP是指在程序运行期间动态地将某段代码切入到指定位置并运行的编程方式。

AOP详解可参考:https://blog.csdn.net/javazejian/article/details/56267036

切点表达式详解可参考:https://www.cnblogs.com/zhangxufeng/p/9160869.html

2-1execution表达式

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型、类名、方法名和参数名等与方法相关的部件。并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法:

execution([visibility-pattern] ret-type-pattern [declaring-type-pattern]method-name-pattern(param-pattern) [throws-pattern])
  • 中括号[]包括的内容表示在写切点表达式时可以省略。而其他的不能省略,但可用通配符代替。
  • visibility-pattern:方法的可见性,如public, protected;
  • ret-type-pattern:方法的返回值类型,如void, Integer;
  • declaring-type-pattern:方法所在类的全路径(可以包括 类名),如com.myaop.MathCalculator;
  • method-name-pattern:方法名,如division();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception。

如下是一个使用execution表达式的例子:

execution(public * com.myaop.MathCalculator.division(Integer,..))

这个切点表达式将会匹配:使用public修饰、返回值为任意类型、是com.myaop.MathCalculator类中的名为division的方法、这个方法可以有多个参数,但第一个参数必须是Integer类型(int不匹配)。

2-2通配符

上述示例中使用了..通配符,通配符主要有两种:

  • *通配符:主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。
  • 如表达式:
execution(* com.myaop.MathCalculator.*())

返回值为任意类型、在com.myaop.MathCalculator类中、无参的方法。
– 如表达式:

execution(* com.myaop.Math*.*())

返回值为任意类型、在com.myaop.Math为前缀的类中、无参的方法。
* ..通配符:表示0个或多个项,主要用于declaring-type-pattern和param-pattern中。如果用于declaring-type-pattern中,则表示匹配当前包及其子包;如果用于param-pattern中,则表示匹配0个或多个参数。
– 如表达式:

execution(* com..divi*(..))

返回值为任意类型、在 com包及其子包下所有以divi开头、参数任意的方法。
特别注意:如果..用于declaring-type-pattern中,在表示匹配当前包及其子包的同时,还相当于在匹配的declaring-type-pattern结果后 再加了一个分隔符(.)。如果将MathCalculator类放在包路径com.myaop.business下,则有:
– *上图中表达式表示为:返回值为任意类型,在包com包及其子包下的所有类的以divi开头、参数任意的方法。

3-1导入AOP依赖

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>4.3.12.RELEASE</version>
</dependency>

具体使用时还需引进spring-context的相关依赖

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>5.2.10.RELEASE</version>
</dependency>

3-2创建业务类

创建业务类(MathCalculator)。

package com.myaop;

import org.springframework.stereotype.Component;

@Component
public class MathCalculator {
    public int division(int dividend, int divisor) {
        System.out.println("--&#x6267;&#x884C;division&#x65B9;&#x6CD5;");
        int result = dividend / divisor;
        return result;
    }
}

3-3创建切面类

package com.myaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
//Aspect&#x6CE8;&#x89E3;&#x53EA;&#x662F;&#x7528;&#x6765;&#x544A;&#x8BC9;&#x5BB9;&#x5668;&#x8FD9;&#x662F;&#x4E00;&#x4E2A;&#x5207;&#x9762;&#x7C7B;&#xFF0C;&#x4F46;&#x5E76;&#x4E0D;&#x80FD;&#x5C06;&#x6B64;&#x7C7B;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A;&#x7EC4;&#x4EF6;&#x6DFB;&#x52A0;&#x8FDB;&#x5BB9;&#x5668;&#x4E2D;
@Aspect
public class MyAspect {

    //&#x5B9A;&#x4E49;&#x5207;&#x70B9;
    @Pointcut("execution(int com.myaop.MathCalculator.*(..))")
    public void pointCut() {
    }

    //&#x524D;&#x7F6E;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x524D;&#x6267;&#x884C;
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("before &#x65B9;&#x6CD5;" + methodName);
    }

    //&#x540E;&#x7F6E;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x540E;&#x6267;&#x884C;&#x3002;&#x65E0;&#x8BBA;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x662F;&#x5426;&#x6B63;&#x5E38;&#x6267;&#x884C;&#xFF08;&#x540E;&#x7F6E;&#x901A;&#x77E5;&#x65E0;&#x8BBA;&#x5982;&#x4F55;&#x90FD;&#x4F1A;&#x88AB;&#x6267;&#x884C;&#xFF09;
    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("after &#x65B9;&#x6CD5;" + methodName);
    }

    /**
     * &#x73AF;&#x7ED5;&#x901A;&#x77E5;&#xFF1A;
     * &#x6CE8;&#x610F;&#xFF1A;
     * 1.joinPoint.proceed()&#x6267;&#x884C;&#x540E;&#x7684;&#x7ED3;&#x679C;&#x9700;&#x8981;&#x8FD4;&#x56DE;&#x51FA;&#x53BB;&#x3002;
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("around &#x65B9;&#x6CD5;" + methodName + "&#xFF0C;proceed()&#x524D;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;");
        Object result = joinPoint.proceed();
        System.out.println("around &#x65B9;&#x6CD5;" + methodName + "&#xFF0C;proceed()&#x540E;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;");
        return result;
    }

    /**
     * &#x8FD4;&#x56DE;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6B63;&#x5E38;&#x6267;&#x884C;&#x5E76;&#x8FD4;&#x56DE;&#x540E;&#x6267;&#x884C;
     * &#x6CE8;&#x610F;&#xFF1A;
     * 1.&#x6CE8;&#x89E3;&#x4E2D;&#x7684;value&#x53C2;&#x6570;&#x9700;&#x8981;&#x653E;&#x5728;&#x6700;&#x524D;&#x9762;
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("afterReturning &#x65B9;&#x6CD5;" + methodName);
    }

    /**
     * &#x5F02;&#x5E38;&#x901A;&#x77E5;&#xFF1A;&#x5728;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6267;&#x884C;&#x8FC7;&#x7A0B;&#x4E2D;&#x51FA;&#x73B0;&#x5F02;&#x5E38;&#x4E14;&#x65B9;&#x6CD5;&#x81EA;&#x52A8;&#x7ED3;&#x675F;&#x540E;&#x6267;&#x884C;
     * &#x6CE8;&#x610F;&#xFF1A;
     * 1.&#x5982;&#x679C;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x51FA;&#x73B0;&#x5F02;&#x5E38;&#x4F46;&#x662F;&#x88AB;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;try...catch&#x6355;&#x83B7;&#x4E86;&#x800C;&#x6CA1;&#x6709;&#x629B;&#x51FA;&#xFF0C;&#x5219;&#x5F02;&#x5E38;&#x901A;&#x77E5;&#x4E0D;&#x4F1A;&#x6267;&#x884C;
     * 2.&#x6CE8;&#x89E3;&#x4E2D;&#x7684;value&#x53C2;&#x6570;&#x9700;&#x653E;&#x5728;&#x6700;&#x524D;&#x9762;&#x3002;
     */
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Exception exception) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("afterThrowing &#x65B9;&#x6CD5;" + methodName);
    }
}

3-4创建配置类

通过配置类将切面和业务类作为组件添加到容器中,并通过@EnableAspectJAutoProxy注解开启切面功能。

package com.myaop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(value = "com.myaop")
@EnableAspectJAutoProxy
public class MyConfiguration {
}

3-5测试切面功能

package com.myaop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        MathCalculator mathCalculator = context.getBean("mathCalculator", MathCalculator.class);
        mathCalculator.division(1, 1);
    }
}

当mathCalculator.division(1,1)时,运行结果为:

around &#x65B9;&#x6CD5;division&#xFF0C;proceed()&#x524D;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;
before &#x65B9;&#x6CD5;division
after &#x65B9;&#x6CD5;division
afterThrowing &#x65B9;&#x6CD5;division
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.myaop.MathCalculator.division(MathCalculator.java:9)
    at com.myaop.MathCalculator$$FastClassBySpringCGLIB$$c5dccaaf.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
    at com.myaop.MyAspect.around(MyAspect.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
    at com.myaop.MathCalculator$$EnhancerBySpringCGLIB$$cf10f693.division(<generated>)
    at com.myaop.Main.main(Main.java:9)
</generated></generated>

4-1spring-context.5.2.4.RELEASE

当使用如下依赖版本时:

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>5.2.4.RELEASE</version>
</dependency>
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>4.3.12.RELEASE</version>
</dependency>

遵循如下规律:

public Object aop(Method method,Object object) {
    try {
        try {
            /*doAround start*/
            doBefore();
            method.invoke(object);
            /*doAround end*/
        }catch(){
            throw ...;
        }
        finally {
            doAfter();
        }
        doAfterReturning();
    } catch (Exception e) {
        doAfterThrowing();
    }
}

doAround start为around通知方法中joinPoint.proceed()之前的代码块;

doAround end为around通知方法中joinPoint.proceed()之后的代码块;

目标方法正常执行的情况下,执行顺序为:@Around @Before 目标方法 @Around @After @AfterReturning;

目标方法抛出了异常的情况下,执行顺序为:@Around @Before 目标方法 @After @AfterThrowing。

4-2spring-context.5.2.10.RELEASE

当使用如下依赖版本时(spring-context.5.2.4RELEASE更新为了spring-context.5.2.10.RELEASE):

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>4.3.12.RELEASE</version>
</dependency>

就不遵循4-1中的规律了。目标方法执行后的通知执行顺序变了。

当mathCalculator.division(1,1)时,运行结果为:

around &#x65B9;&#x6CD5;division&#xFF0C;proceed()&#x524D;&#x7684;&#x4EE3;&#x7801;&#x5757;&#x6267;&#x884C;
before &#x65B9;&#x6CD5;division
afterThrowing &#x65B9;&#x6CD5;division
after &#x65B9;&#x6CD5;division
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.myaop.MathCalculator.division(MathCalculator.java:9)
    at com.myaop.MathCalculator$$FastClassBySpringCGLIB$$c5dccaaf.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
    at com.myaop.MyAspect.around(MyAspect.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at com.myaop.MathCalculator$$EnhancerBySpringCGLIB$$adde1634.division(<generated>)
    at com.myaop.Main.main(Main.java:9)

Process finished with exit code 1
</generated></generated>

Original: https://www.cnblogs.com/certainTao/p/15363906.html
Author: certainTao
Title: @Aspect

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/713063/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Git的基本使用

    基础操作 1.选择一个合适的地方,创建一个新目录 mkdir learngit cd learngit 2.通过 git init命令把这个目录变成Git可以管理的仓库 git i…

    技术杂谈 2023年7月24日
    085
  • linux学习之联网问题解决

    (centos7)linux隔日重启后发现无法联网解决方案 1.运行命令 ip addr 查看 ip地址 2.运行命令 vi /etc/sysconfig/network-scri…

    技术杂谈 2023年6月21日
    092
  • 跨域

    同源策略指三个相同:协议相同、域名相同、端口相同,有一个不同即非同源。 主域与子域、域名与域名对应的IP。都是非同源的 同源策略可以算是web安全的基石,没有同源策略就么有安全可言…

    技术杂谈 2023年5月31日
    083
  • 通过过滤器实现前后端分离的跨域问题

    跨域指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。在做前后端分离项目的时候就需要解决此问题。 创建过滤器解决跨域问…

    技术杂谈 2023年7月11日
    062
  • gin protobuf客户端测试

    gin protobuf客户端测试 gin protobuf客户端测试 // clientGIN project main.go package main import ( &qu…

    技术杂谈 2023年5月30日
    080
  • 牛腩新闻公布系统总结(三)—-点滴知识

    这篇博客呢主要是讲一下我在做系统的过程中积累下来的感觉非经常常使用但之前没接触过或者有些难理解的地方,与大家分享: 首先,说一下CSS+Div,这个内容在 CSS+DIV 这篇博客…

    技术杂谈 2023年5月31日
    097
  • 【LEETCODE】71、验证二叉树的前序序列化

    简单粗暴,代码有待优化,不过自己独立完成,没有参考任何材料,还是比较满意的 package y2019.Algorithm.stack.medium; import java.ut…

    技术杂谈 2023年7月24日
    061
  • 【转】SVG动态图标是如何实现的

    这篇文章给大家分享的内容是SVG动态图标是如何实现的,有需要的朋友可以参考一下。 在 loading.io 上能看到好多效果惊艳的loading图标。它们都是用svg写成的,寥寥几…

    技术杂谈 2023年6月1日
    077
  • 【赵渝强老师】HBase的体系架构

    一、什么是HBase? HBase是一个基于HDFS之上的分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文”BigTable大表…

    技术杂谈 2023年7月24日
    083
  • Sublime Text 3 中文乱码/符的解决

    本方法对Sublime Text 3211版本已验证可用。 Sublime Text3默认不支持GBK的编码格式,所以会出现乱符的现象。 解决方法如下: 安装Package Con…

    技术杂谈 2023年5月31日
    088
  • 一张动图,让你明白时域和频域的关系

    看明白了这张图,就可以了解为什么既要做时域分析也要做频域分析了吧。 简单总结下,时域和频域的关系如下: 时域是信号在时间轴随时间变化的总体概括。 频域是把时域波形的表达式做傅立叶等…

    技术杂谈 2023年5月31日
    0103
  • JS跨域通信方法及SF相关问题

    iframe的跨域通信比较推荐的是采用信使的方式。基本地原理是在iframe的内部再创建一个iframe(称之为信使),父子页面轮询信使的window.name,父子页面各自使用变…

    技术杂谈 2023年7月24日
    074
  • Go 1.19中终于实现了SetMemoryLimit的功能

    Go 1.19中终于实现了 SetMemoryLimit的功能。Go的GC并不像Java那样提供了很多的参数可以调整,目前也就有 GOGC这么一个参数,所以能增加一个可以调整GC的…

    技术杂谈 2023年5月30日
    090
  • Mysql-强制改密

    MySQL V8.0.22 [mysqld] 跳过登录验证 skip-grant-tables use mysql; update user set authentication_…

    技术杂谈 2023年6月21日
    0102
  • PyTorch 介绍 | 保存和加载模型

    本节我们将会看到如何保存模型状态、加载和运行模型预测 import torch import torchvision.models as models 保存和加载模型权重 PyTo…

    技术杂谈 2023年7月25日
    0116
  • 使用seldom编写http接口用例

    在编写接口用例的过程中,针对一个接口,往往只是参数不同,那么参数化就非常有必要了。 seldom 中参数化的用法非常灵活,这里仅介绍 @file_data() 的N种玩法。 二维列…

    技术杂谈 2023年5月31日
    092
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球