spring AOP中pointcut表达式详解

📢📢📢📣📣📣
哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝
一位上进心十足的【Java ToB端大厂领域博主】!😜😜😜
喜欢java和python,平时比较懒,能用程序解决的坚决不手动解决😜😜😜

✨ 如果有对【java】感兴趣的【小可爱】,欢迎关注我

❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
————————————————

如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。

由于项目很忙,最近很少有时间更新文章和大家分享,已经很及没更新文章了,让各位久等了。最近忙里偷闲抽空分享一些aop的知识。详细大家对这个很熟悉但也陌生,没有系统的整理过这个知识。

 

本文主要介绍spring aop中9种切入点表达式的写法,相信不少同学跟我一样,没有系统的整理过aop中的pointcut的表达式。今天我们就抽空讲解一下pointcut表达式的用法和含义。

Spring AOP支持的AspectJ表达式概览:

  • execution: 匹配方法执行的切入点。Spring AOP主要使用的切点标识符。
  • within: 限制匹配在特定类型内的连接点。(给定class的所有方法)
  • this: 限制匹配是给定类型的实例的bean引用(Spring AOP proxy)的连接点。(代理类是给定类型的类的所有方法)
  • target: 限制匹配是给定类型的实例的目标对象(被代理对象)的连接点。(目标对象是给定类型的类的所有方法)
  • args: 匹配参数是给定类型的连接点。(方法入参是给定类型的方法)
  • @target: 匹配有给定注解的执行对象的class的连接点。(目标对象class上有给定注解的类的所有方法)
  • @args: 匹配实际传递的参数的运行时类型有给定的注解的连接点。(方法入参上有给定注解)
  • @within: 匹配有给定注解的类型的连接点。(class上有给定注解的class的所有方法)
  • @annotation: 匹配连接点的subject有给定注解的连接点。(方法上有给定注解的方法)
     

1.execute表达式

execution(* com.xx.web.controller..*.*(..))

参数说明

符号  含义
execution() 表达式的主体;
第一个”*“符号  表示返回值的类型任意;
com.sample.service.impl AOP所切的服务的包名
包名后面的”..“ 表示当前包及子包
第二个”*“符号  表示类名,*即所有类
.*(..) 表示任何方法名,括号表示参数,两个点表示任何参数类型

基本语法格式为: execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)

  • 修饰符匹配(modifier-pattern?)
  • 返回值匹配(ret-type-pattern):可以为*,表示任何返回值,全路径的类名等
  • 类路径匹配(declaring-type-pattern?)
  • 方法名匹配(name-pattern):可以指定方法名 或者*,代表所有。
  • set*, 代表以set开头的所有方法
  • 参数匹配((param-pattern)):可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用“*”来表示匹配任意类型的参数
  • String表示匹配一个String参数的方法;
  • *,String 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;
  • 可以用..表示零个或多个任意参数
  • 异常类型匹配(throws-pattern?)
     

下面是官网中的一些实例:

Aspect Oriented Programming with Spring :: Spring Framework

拦截任意公共方法

execution(public * *(..))

拦截以set开头的任意方法

execution(* set*(..))

拦截类或者接口中的方法

execution(* com.xyz.service.AccountService.*(..))
拦截 AccountService(类、接口)中定义的所有方法

拦截包中定义的方法,不包含子包中的方法

execution(* com.xyz.service.*.*(..))
拦截 com.xyz.service包中所有类中任意方法,不包含子包中的类

拦截包或者子包中定义的方法

execution(* com.xyz.service..*.*(..))
拦截 com.xyz.service包或者子包中定义的所有方法

// 带?的表示可选
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throws-pattern?)
  1. 方法修饰符匹配 modifier-pattern(可选)
  2. 方法返回值匹配 ret-type-pattern
  3. 类路径匹配 declaring-type-pattern(可选)
  4. 方法名和参数匹配 name-pattern(param-pattern)
  5. 异常类型匹配 throws-pattern(可选)

 

简单事例

下面是execution的简单例子:

有两个IService接口分别有m1和m2方法,现在

ServiceImpl实现两个接口

实现切面Interceptor 切点如下

@Pointcut("execution(* com.ms.aop.execution.ServiceImpl.*(..))")
Interceptor1

public interface IService {void m1();
}

 

public interface IService2 {void m2();
}
package com.ms.aop.execution;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
@Slf4j
public class Interceptor1 {@Pointcut("execution(* com.ms.aop.execution.ServiceImpl.*(..))")public void pointcut() {}@Around("pointcut()")public Object invoke(ProceedingJoinPoint invocation) throws Throwable {log.info("方法执行之前");Object result = invocation.proceed();log.info("方法执行完毕");return result;}
}
@Slf4j
@Component
public class ServiceImpl implements IService, IService2 {@Overridepublic void m1() {log.info("切入点m1的execution测试!");}@Overridepublic void m2() {log.info("切入点m2的execution测试!");}
}

 

测试类

@ComponentScan(basePackageClasses={Client.class})
@EnableAspectJAutoProxy
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);IService2 service = annotationConfigApplicationContext.getBean(IService2.class);IService service1 = annotationConfigApplicationContext.getBean(IService.class);service.m2();service1.m1();}
}

执行结果:

15:07:00.304 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行之前
15:07:00.304 [main] INFO com.ms.aop.execution.ServiceImpl - 切入点m2的execution测试!
15:07:00.304 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行完毕


15:07:00.305 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行之前
15:07:00.305 [main] INFO com.ms.aop.execution.ServiceImpl - 切入点m1的execution测试!
15:07:00.305 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行完毕

分析:

  1. @EnableAspectJAutoProxy:表示若spring创建的对象如果实现了接口,默认使用jdk动态代理,如果没有实现接口,使用cglib创建代理对象
  2. 所以 service 是使用jdk动态代理生成的对象,service instanceof ServiceImpl 为 false
  3. @Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")表示被spring代理之后生成的对象必须为com.ms.aop.jthis.demo1.ServiceImpl才会被拦截,但是service不是ServiceImpl类型的对象了,所以不会被拦截
  4. 修改代码

    @EnableAspectJAutoProxy(proxyTargetClass = true)
    proxyTargetClass=true表示使用cglib来生成代理对象

执行结果

17:34:43.297 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行之前
17:34:43.307 [main] INFO com.ms.aop.execution.ServiceImpl - 切入点m2的execution测试!
17:34:43.308 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行完毕


17:34:43.308 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行之前
17:34:43.308 [main] INFO com.ms.aop.execution.ServiceImpl - 切入点m1的execution测试!
17:34:43.308 [main] INFO com.ms.aop.execution.Interceptor1 - 方法执行完毕

使用cglib方式和jdk代理的方式效果是一致的。

排除和包含

实现某些的排除:@Pointcut切入点排除某一些类或者方法不进行拦截

	// 扫描controller层@Pointcut("execution(* com.xx.web.controller..*.*(..)) ")public void includePointcat() {}// 排除controller类@Pointcut("execution(* com.xx.web.controller.TempController.*(..)) ")public void excludePointcut() {}//切面配置@AfterReturning("includePointcat() && !excludePointcut()")public void saveSysLog(JoinPoint joinPoint) throws IOException {String className = joinPoint.getSignature().getDeclaringType().getSimpleName();String methodName = joinPoint.getSignature().getName();logger.info("{}.{} start", className, methodName);}

includePointcat:切入点为controller下所有类。

excludePointcut:切入点为controller下TempController类。

saveSysLog:切入点为满足 includePointcat且不满足excludePointcut的切入点的范围


2.within表达式

表达式格式:包名.* 或者 包名..*

拦截包中任意方法,不包含子包中的方法

within(com.xyz.service.*)
拦截service包中任意类的任意方法

拦截包或者子包中定义的方法

within(com.xyz.service..*)
拦截service包及子包中任意类的任意方法

within与execution相比,粒度更大,仅能实现到包和接口、类级别。而execution可以精确到方法的返回值,参数个数、修饰符、参数类型等

3.this表达式

代理对象为指定的类型会被拦截

目标对象使用aop之后生成的代理对象必须是指定的类型才会被拦截,注意是目标对象被代理之后生成的代理对象和指定的类型匹配才会被拦截
this(com.xyz.service.AccountService)

例如下面的例子

package com.ms.aop.jthis.demo1;
​
public interface IService {void m1();
}package com.ms.aop.jthis.demo1;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
​
@Slf4j
@Component
public class ServiceImpl implements IService {@Overridepublic void m1() {log.info("切入点this测试!");}
}package com.ms.aop.jthis.demo1;
​
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class Interceptor1 {
​@Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")public void pointcut() {}
​@Around("pointcut()")public Object invoke(ProceedingJoinPoint invocation) throws Throwable {log.info("方法执行之前");Object result = invocation.proceed();log.info("方法执行完毕");return result;}
}package com.ms.aop.jthis.demo1;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
​
@ComponentScan(basePackageClasses = {Client.class})
@EnableAspectJAutoProxy
@Slf4j
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);IService service = annotationConfigApplicationContext.getBean(IService.class);service.m1();log.info("{}", service instanceof ServiceImpl);}
}

注意这里的代理对象类型的定义

 @Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")

结果:

10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false
  1. @EnableAspectJAutoProxy:表示若spring创建的对象如果实现了接口,默认使用jdk动态代理,如果没有实现接口,使用cglib创建代理对象
  2. 所以 service 是使用jdk动态代理生成的对象,service instanceof ServiceImpl 为 false
  3. @Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")表示被spring代理之后生成的对象必须为com.ms.aop.jthis.demo1.ServiceImpl才会被拦截,但是service不是ServiceImpl类型的对象了,所以不会被拦截
  4. 修改代码

    @EnableAspectJAutoProxy(proxyTargetClass = true)
    proxyTargetClass=true表示使用cglib来生成代理对象
    执行结果:

    10:34:50.736 [main] INFO com.ms.aop.jthis.demo1.Interceptor1 - 方法执行之前
    10:34:50.755 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!
    10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Interceptor1 - 方法执行完毕
    10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Client - true
    service 为 ServiceImpl类型的对象,所以会被拦截

4.target表达式

目标对象为指定的类型被拦截

target(com.xyz.service.AccountService)
目标对象为AccountService类型的会被代理
package com.ms.aop.target;
​
public interface IService {void m1();
}package com.ms.aop.target;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
​
@Slf4j
@Component
public class ServiceImpl implements IService {@Overridepublic void m1() {log.info("切入点target测试!");}
}package com.ms.aop.target;
​
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
​
@Aspect
@Component
@Slf4j
public class Interceptor1 {
​@Pointcut("target(com.ms.aop.target.ServiceImpl)")public void pointcut() {}
​@Around("pointcut()")public Object invoke(ProceedingJoinPoint invocation) throws Throwable {log.info("方法执行之前");Object result = invocation.proceed();log.info("方法执行完毕");return result;}
}package com.ms.aop.target;
​
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
​
@ComponentScan(basePackageClasses = {Client.class})
@EnableAspectJAutoProxy
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);IService service = annotationConfigApplicationContext.getBean(IService.class);service.m1();}
}

执行结果

10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法执行之前
10:49:01.674 [main] INFO com.ms.aop.target.ServiceImpl - 切入点target测试!
10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法执行完毕

this 和 target 的不同点

  1. this作用于代理对象,target作用于目标对象
  2. this表示目标对象被代理之后生成的代理对象和指定的类型匹配会被拦截,匹配的是代理对象
  3. target表示目标对象和指定的类型匹配会被拦截,匹配的是目标对象

5.args 表达式

匹配方法中的参数

@Pointcut("args(com.ms.aop.args.demo1.UserModel)")
匹配只有一个参数,且类型为 com.ms.aop.args.demo1.UserModel

匹配多个参数

args(type1,type2,typeN)

匹配任意多个参数

@Pointcut("args(com.ms.aop.args.demo1.UserModel,..)")
匹配第一个参数类型为 com.ms.aop.args.demo1.UserModel的所有方法,  .. 表示任意个参数

6.@target表达式

匹配的目标对象的类有一个指定的注解

@target(com.ms.aop.jtarget.Annotation1)
目标对象中包含 com.ms.aop.jtarget.Annotation1注解,调用该目标对象的任意方法都会被拦截

7.@within表达式

指定匹配必须包含某个注解的类里的所有连接点

@within(com.ms.aop.jwithin.Annotation1)
声明有 com.ms.aop.jwithin.Annotation1注解的类中的所有方法都会被拦截

@target 和 @within 的不同点

  1. @target(注解A):判断被调用的目标对象中是否声明了注解A,如果有,会被拦截
  2. @within(注解A): 判断被调用的方法所属的类中是否声明了注解A,如果有,会被拦截
  3. @target关注的是被调用的对象,@within关注的是调用的方法所在的类

8.@annotation表达式

匹配有指定注解的方法(注解作用在方法上面)

@annotation(com.ms.aop.jannotation.demo2.Annotation1)
被调用的方法包含指定的注解

9.@args表达式

方法参数所属的类型上有指定的注解,被匹配

注意:是 方法参数所属的类型上有指定的注解,不是方法参数中有注解

  • 匹配1个参数,且第1个参数所属的类中有Anno1注解
@args(com.ms.aop.jargs.demo1.Anno1)
  • 匹配多个参数,且多个参数所属的类型上都有指定的注解
@args(com.ms.aop.jargs.demo1.Anno1,com.ms.aop.jargs.demo1.Anno2)
  • 匹配多个参数,且第一个参数所属的类中有Anno1注解
@args(com.ms.aop.jargs.demo2.Anno1,..)

 

项目实战:

下面是切面的一个项目应用 实现服务日志的记录

@Aspect
@Component
@Slf4j
public class SealServiceControllerAspect {@Autowiredprivate InterfaceLogDao interfaceLogDao;/*** 日志入库异步模式,线程池用fk pool*/private static ForkJoinPool LOG_THREAD_POOL = new ForkJoinPool(4);@Pointcut("" +"execution(* com.xx.seal.RestSignContractResource.*(..))" +"|| execution(* com.xx.controller.seal.ContractProcessSignResource.*(..))")public void pointCuts() {}@Around("pointCuts()")public Object invoke(ProceedingJoinPoint invocation) throws Throwable {final InterfaceLogPO po = new InterfaceLogPO();Object[] inParam = invocation.getArgs();JSONArray inParams = new JSONArray();if (inParam != null) {Arrays.stream(inParam).forEach(p -> {try {if (p instanceof String||p instanceof Number ||p instanceof Boolean){inParams.add(p);}else if (JSONUtils.isArray(p)) {try {inParams.add(JSONArray.fromObject(p));} catch (Exception e) {log.warn("==>this aspect[{}] can not get input param ", invocation.getSignature().getName());}} else {try {inParams.add(JSONObject.fromObject(p));} catch (Exception e) {log.warn("==>this aspect[{}] can not get input param ", invocation.getSignature().getName());}}} catch (Exception e) {log.warn("==>aspect error :can not fetch args --->{}", e.getMessage());}});}if (invocation.getTarget().getClass().getName().endsWith("Resource") ||invocation.getTarget().getClass().getName().endsWith("Controller")) {po.setCategory("REST");} else {po.setCategory("SERVICE");}po.setAction(invocation.getTarget().getClass().getName() + "@" + invocation.getSignature().getName());po.setActionDesc("");// 从swagger的@Api注解中取po.setInputParam(inParams.toString());po.setTs(new Date());po.setCallStatus("OK");po.setUserId(InvocationInfoProxy.getUserid());po.setUserName(InvocationInfoProxy.getUsername());Object result = null;try {result = invocation.proceed();} catch (Throwable throwable) {po.setCallStatus("ERR");StringBuilder sb = new StringBuilder( throwable.getMessage()+"\n");sb.append(ExceptionUtils.getFullStackTrace(throwable)).append("\n");po.setErrorMessage(sb.toString());throw throwable;} finally {if (result != null) {if (result instanceof String  ||result instanceof Number ||result instanceof Boolean){po.setOutputResult(result.toString());}else if (JSONUtils.isArray(result)) {try {po.setOutputResult(JSONArray.fromObject(result).toString());} catch (Exception e) {log.warn("==>this aspect[{}] can not get output result ", invocation.getSignature().getName());}} else {try {po.setOutputResult(JSONObject.fromObject(result).toString());} catch (Exception e) {log.warn("==>this aspect[{}] can not get output result", invocation.getSignature().getName());}}/*这部分以后要改造成基于接口的插件式!!!*/if (result instanceof Result && ((Result) result).getData() != null) {//后续考虑引入策略模式if (((Result) result).getData() instanceof ResultContractProcessDTO) {String bizKey = ((ResultContractProcessDTO) ((Result) result).getData()).getProcessId();po.setBizKey(bizKey);} else {try {JSONObject outputResult = JSONObject.fromObject(((Result) result).getData());po.setBizKey(outputResult.getString("id"));} catch (Exception e) {log.warn("==>this aspect[{}] can not get biz key", invocation.getSignature().getName());}}}if (result instanceof  ResultContractProcessDTO){String bizKey = ((ResultContractProcessDTO) result).getProcessId();po.setBizKey(bizKey);}}interfaceLogDao.save(po);}return result;}}

希望这个文章能让大家有所收获,哪怕有一点点的收获,这样我写这个文章也就值得了。

创作不易,请给小编点个赞吧,一个字一个字敲下来很费时间和精力的😄 

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

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

相关文章

Qt中的信号与槽(Signals and Slots)

Qt中的信号与槽&#xff08;Signals and Slots&#xff09;是一种用于对象间通信的机制&#xff0c;常用于处理用户界面事件和数据更新等情况。通过信号与槽&#xff0c;可以实现对象之间的解耦和灵活的交互。 信号&#xff08;Signal&#xff09;是对象发出的事件或通知&…

基于vscode连接到远程服务中debug

本文章主要讲解以下两点的任务 1.在windows的vscode中去debug 本机子系统wsl2中运行的docker容器 该篇文件参考知乎上这篇文章 vscode远程连接到本机 wsl2子系统 中正在运行的 docker容器&#xff0c;该docker中有一个flask实例&#xff0c;通过vscode远程debug它 1.1安装v…

Modbus tcp转ETHERCAT在Modbus软件中的配置方法

Modbus tcp和ETHERCAT是两种不同的协议&#xff0c;这给工业生产带来了很大的麻烦&#xff0c;因为这两种设备之间无法通讯。但是&#xff0c;远创智控YC-ECT-TCP网关的出现&#xff0c;却为这个难题提供了解决方案。 YC-ECT-TCP网关能够连接到Modbus tcp总线和ETHERCAT总线中…

Kubernetes —Pod 和容器日志

日志架构 应用日志可以让你了解应用内部的运行状况。日志对调试问题和监控集群活动非常有用。 大部分现代化应用都有某种日志记录机制。同样地&#xff0c;容器引擎也被设计成支持日志记录。 针对容器化应用&#xff0c;最简单且最广泛采用的日志记录方式就是写入标准输出和标…

容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)

目录 通过元素自身实现比较规则 通过比较器实现比较规则 双例集合 TreeMap容器的使用 Iterator接口 Collections工具类 通过元素自身实现比较规则 在元素自身实现比较规则时&#xff0c;需要实现Comparable接口中的 compareTo方法&#xff0c;该方法中用来定义比较规则。T…

【IoT物联网】IoT小程序在展示中央空调采集数据和实时运行状态上的应用

利用前端语言实现跨平台应用开发似乎是大势所趋&#xff0c;跨平台并不是一个新的概念&#xff0c;“一次编译、到处运行”是老牌服务端跨平台语言Java的一个基本特性。随着时代的发展&#xff0c;无论是后端开发语言还是前端开发语言&#xff0c;一切都在朝着减少工作量&#…

MySQL库表操作的作业

1.创建数据库 create database Market&#xff1b; mysql> show databases; -------------------- | Database | -------------------- | information_schema | | Market | | db1 | | mysql | | performance_schema | | …

如何用一部手机进行人体全身三维扫描

人体建模的应用真的是涵盖到了我们生活中的方方面面&#xff0c;真人潮玩、服饰定制、医疗康复、3D数字人等等领域&#xff0c;都离不开人体建模。 提到给人体建模&#xff0c;大家脑海里第一个浮现的画面&#xff0c;大多会是坐在电脑屏幕前&#xff0c;打开某个熟悉的建模的…

制作搭建宠物商城小程序,打造便捷的宠物购物体验

随着汽车行业的快速发展&#xff0c;越来越多的消费者开始关注汽车零配件的购买。为了提供更好的购物体验和便利&#xff0c;许多汽配商城开始关注并制作汽配商城小程序。那么&#xff0c;什么是汽配商城小程序&#xff1f;它又有哪些好处呢&#xff1f;本文将为您简单介绍汽配…

Transformer网络学习记录——基于空间约束自注意力和Transformer的RGB-D显著性检测方法研究

基于图半监督学习和图卷积的目标分割与跟踪算法研究 (wanfangdata.com.cn) 只能说看不懂&#xff0c;记录是为了有耐心慢消化 原文&#xff1a; 网络整体为通用的编码器-解码器架构 &#xff0c;总体上由骨干编码器、交互编码器、RGB 解码器、深度解码器组成。 具体来说&#…

操作系统接口 MIT 6.828 - 1. Lab 01: Xv6 and Unix utilities

本文会将lab1中的思路以及知识点进行分析&#xff0c;并作为作者学习MIT 6.828的一个学习总结&#xff0c;希望能够帮助到学习该lab的同学们 中文版书籍&#xff1a;中文版书籍 实验教案地址&#xff1a;教案地址 操作系统接口 在操作系统中&#xff0c;为了能够有效地与操作系…

【SCI征稿】计算机算法、通信、人工智能、网络、物联网、机器学习等领域,13本期刊影响因子上涨,这几本期刊录用快

2023年JCR发布后&#xff0c;计算机领域SCI期刊有13本影响因子上涨&#xff0c;审稿周期短&#xff0c;进展顺利&#xff1a; 1️⃣IF&#xff1a;6.0-7.0↑&#xff0c;JCR2区&#xff0c;中科院3区&#xff0c;SCI&EI 双检&#xff0c;CCF-C类 征稿领域&#xff1a;概率…