补充学习: app注解学习了解

本文详细介绍了Spring AOP的基本概念,包括其实现原理、与AspectJ的区别,以及JDK动态代理与Cglib的对比。同时,文章还提供了使用Spring AOP的步骤,包括定义业务组件、切点、增强处理方法等,以及相关的依赖介绍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载:https://www.cnblogs.com/hellxz/p/9629012.html

补充学习aop

Spring AOP基本概念
是一种动态编译期增强性AOP的实现
与IOC进行整合,不是全面的切面框架
与动态代理相辅相成
有两种实现:基于jdk动态代理、cglib
Spring AOP与AspectJ区别
Spring的AOP是基于动态代理的,动态增强目标对象,而AspectJ是静态编译时增强,需要使用自己的编译器来编译,还需要织入器
使用AspectJ编写的java代码无法直接使用javac编译,必须使用AspectJ增强的ajc增强编译器才可以通过编译,写法不符合原生Java的语法;而Spring AOP是符合Java语法的,也不需要指定编译器去编译,一切都由Spring 处理。
JDK动态代理与Cglib的区别
jdk的动态代理需要实现接口 InvocationHandler
cglib无需实现接口,使用字节码技术去修改class文件使继承
spring默认使用jdk动态代理,如果没有实现接口会使用cglib
使用步骤
定义业务组件
定义切点(重点)
定义增强处理方法(切面方法)
依赖
jar包依赖,除此以外还有spring依赖

aspectjweaver.jar
aspectjrt.jar
aspectj.jar
aopalliance.jar
maven依赖

<dependencies>
    <!-- 有此依赖会远程下载其它相关依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    <!-- aspectJ AOP 织入器 -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.9</version>
    </dependency>

</dependencies>

注解方式开发
扫描Aspect增强的类
<context:component-scan base-package="">
<context:include-filter type=“annotation”
expression=“org.aspectj.lang.annotation.Aspect”/>
</context:component-scan>
开启@AspectJ支持 aop:aspectj-autoproxy/
使用@AspectJ注解来标记一个切面类(spring不会将切面注册为Bean也不会增强,但是需要扫描)
使用其它注解进行开发(如下)
常用注解的使用
@Before:在切点方法前执行
在增强的方法上@Before(“execution(* 包名..(…))”)
上述表达式可使用pointcut或切入表达式,效果一致,之后不再赘述
切点方法没有形参与返回值
示例代码

@Aspect
public class AuthAspect {

//定义切点
@Pointcut("execution(* com.cnblogs.hellxz.service.*.*(..))")
public void pointCut() {}

//前置处理
@Before("pointCut()")
public void auth() {
    System.out.println("模拟权限检查……");
}

}
@After:在切点方法后执行
用法同@Before
@Around:在切点方法外环绕执行
在增强的方法上@Around(“execution(* 包名.*(…))”)或使用切点@Around(“pointcut()”)
接收参数类型为ProceedingJoinPoint,必须有这个参数在切面方法的入参第一位
返回值为Object
需要执行ProceedingJoinPoint对象的proceed方法,在这个方法前与后面做环绕处理,可以决定何时执行与完全阻止方法的执行
返回proceed方法的返回值
@Around相当于@Before和@AfterReturning功能的总和
可以改变方法参数,在proceed方法执行的时候可以传入Object[]对象作为参数,作为目标方法的实参使用。
如果传入Object[]参数与方法入参数量不同或类型不同,会抛出异常
通过改变proceed()的返回值来修改目标方法的返回值
示例代码

@Aspect
public class TxAspect {

//环绕处理
@Around("execution(* com.cnblogs.hellxz.service.*.*(..))")
Object auth(ProceedingJoinPoint point) {
    
    Object object = null;
    try {
        System.out.println("事务开启……");
        //放行
        object = point.proceed();
        System.out.println("事务关闭……");
    } catch (Throwable e) {
        e.printStackTrace();
    }
    
    return object;
}

}
@AfterRetruning: 在方法返回之前,获取返回值并进行记录操作
和上边的方法不同的地方是该注解除了切点,还有一个返回值的对象名
不同的两个注解参数:returning与pointcut,其中pointcut参数可以为切面表达式,也可为切点
returning定义的参数名作为切面方法的入参名,类型可以指定。如果切面方法入参类型指定Object则无限制,如果为其它类型,则当且仅当目标方法返回相同类型时才会进入切面方法,否则不会
还有一个默认的value参数,如果指定了pointcut则会覆盖value的值
与@After类似,但@AfterReturning只有方法成功完成才会被织入,而@After不管结果如何都会被织入
虽然可以拿到返回值,但无法改变返回值

示例代码

@Aspect
public class AfterReturningAspect {

@AfterReturning(returning="rvt",
        pointcut = "execution(* com.cnblogs.hellxz.service.*.*(..))")
//声明rvt时指定的类型会限定目标方法的返回值类型,必须返回指定类型或者没有返回值
//rvt类型为Object则是不对返回值做限制
public void log(Object rvt) {
    System.out.println("获取目标返回值:"+ rvt);
    System.out.println("假装在记录日志……");
}

/**
 * 这个方法可以看出如果目标方法的返回值类型与切面入参的类型相同才会执行此切面方法
 * @param itr
 */
@AfterReturning(returning="itr", 
        pointcut="execution(* com.cnblogs.hellxz.service.*.*(..))")
public void test(Integer itr) {
    System.out.println("故意捣乱……:"+ itr);
}

}
@AfterThrowing: 在异常抛出前进行处理,比如记录错误日志
与@AfterReturning类似,同样有一个切点和一个定义参数名的参数——throwing
同样可以通过切面方法的入参进行限制切面方法的执行,e.g. 只打印IOException类型的异常, 完全不限制可以使用Throwable类型
pointcut使用同@AfterReturning
还有一个默认的value参数,如果指定了pointcut则会覆盖value的值
如果目标方法中的异常被try catch块捕获,此时异常完全被catch块处理,如果没有另外抛出异常,那么还是会正常运行,不会进入AfterThrowing切面方法
示例代码

@Aspect
public class AfterThrowingAspect {

@Pointcut("execution(* com.cnblogs.hellxz.test.*.*(..))")
public void pointcut() {}

/**
 * 如果抛出异常在切面中的几个异常类型都满足,那么这几个切面方法都会执行
 */
@AfterThrowing(throwing="ex1", 
        pointcut="pointcut()")
//无论异常还是错误都会记录
//不捕捉错误可以使用Exception
public void throwing(Throwable ex1) {
    System.out.println("出现异常:"+ex1);
}

@AfterThrowing(throwing="ex", 
        pointcut="pointcut()")
//只管IOException的抛出
public void throwing2(IOException ex) {
    System.out.println("出现IO异常: "+ex);
}

}
pointcut定义的切点方法在@Before/@After/@Around需要写在双引号中,e.g. @Before(“pointCut()”)

JoinPoint的概念与方法说明
概念
顾名思义,连接点,织入增强处理的连接点
程序运行时的目标方法的信息都会封装到这个连接点对象中
此连接点只读
方法说明
Object[] getArgs():返回执行目标方法时的参数
Signature getSignature():返回被增强方法的相关信息,e.g 方法名 etc
Object getTarget():返回被织入增强处理的目标对象
Object getThis():返回AOP框架目标对象生成的代理对象
使用
在@Before/@After/@AfterReturning/@AfterThrowing所修饰的切面方法的参数列表中加入JoinPoint对象,可以使用这个对象获得整个增强处理中的所有细节
此方法不适用于@Around, 其可用ProceedingJoinPoint作为连接点
ProceedingJoinPoint的概念与方法说明
概念
是JoinPoint的子类
与JoinPoint概念基本相同,区别在于是可修改的
使用@Around时,第一个入参必须为ProceedingJoinPoint类型
在@Around方法内时需要执行proceed()或proceed(Object[] args)方法使方法继续,否则会一直处于阻滞状态
方法说明
ProceedingJoinPoint是JoinPoint的子类,包含其所有方法外,还有两个公有方法

Object proceed():执行此方法才会执行目标方法
Object proceed(Object[] args):执行此方法才会执行目标方法,而且会使用Object数组参数去代替实参,如果传入Object[]参数与方法入参数量不同或类型不同,会抛出异常

通过修改proceed方法的返回值来修改目标方法的返回值

编入的优先级
优先级最高的会最先被织入,在退出连接点的时候,具有最高的优先级的最后被织入

当不同切面中两个增强处理切入同一连接点的时候,Spring AOP 会使用随机织入的方式
如果想要指定优先级,那么有两种方案:

让切面类实现 org.springframework.core.Ordered接口,实现getOrder方法,返回要指定的优先级
切面类使用@Order修饰,指定一个优先级的值,值越小,优先级越高
访问目标方法的形参
除了使用JoinPoint或ProceedingJoinPoint来获取目标方法的相关信息外(包括形参),如果只是简单访问形参,那么还有一种方法可以实现

在pointcut的execution表达式之后加入&& args(arg0,arg1)这种方式
@Aspect
public class AccessInputArgs {

@Before("execution(* com.cnblogs.hellxz.test.*.*(..)) && args(arg0, arg1)")
public void access(String arg0, String arg1){
    System.out.println("接收到的参数为arg0="+arg0+",arg1="+arg1);
}

}
注意:通过这种方式会只匹配到方法只有指定形参数量的方法,并且,在切面方法中指定的类型会限制目标方法,不符合条件的不会进行织入增强

定义切入点
通过定义切入点,我们可以复用切点,减少重复定义切点表达式等
切入点定义包含两个部分:

切入点表达式
包含名字和任意参数的方法签名
使用@Pointcut注解进行标记一个无参无返回值的方法,加上切点表达式

@Pointcut("execution(* com.cnblogs.hellxz.test.*.*(..))")
public void pointcut(){}

切入点指示符
Spring AOP 支持10种切点指示符:execution、within、this、target、args、@target、@args、@within、@annotation、bean下面做下简记(没有写@Pointcut(),请注意):

execution: 用来匹配执行方法的连接点的指示符。
用法相对复杂,格式如下:execution(权限访问符 返回值类型 方法所属的类名包路径.方法名(形参类型) 异常类型)
e.g. execution(public String com.cnblogs.hellxz.test.Test.access(String,String))
权限修饰符和异常类型可省略,返回类型支持通配符,类名、方法名支持*通配,方法形参支持…通配

within: 用来限定连接点属于某个确定类型的类。
within(com.cnblogs.hellxz.test.Test)
within(com.cnblogs.hellxz.test.) //包下类
within(com.cnblogs.hellxz.test…) //包下及子包下

this和target: this用于没有实现接口的Cglib代理类型,target用于实现了接口的JDK代理目标类型
举例:this(com.cnblogs.hellxz.test.Foo) //Foo没有实现接口,使用Cglib代理,用this
实现了个接口public class Foo implements Bar{…}
target(com.cnblogs.hellxz.test.Test) //Foo实现了接口的情况
args: 对连接点的参数类型进行限制,要求参数类型是指定类型的实例。
args(Long)
@target: 用于匹配类头有指定注解的连接点
@target(org.springframework.stereotype.Repository)
@args: 用来匹配连接点的参数的,@args指出连接点在运行时传过来的参数的类必须要有指定的注解
java @Pointcut("@args(org.springframework.web.bind.annotation.RequestBody)") public void methodsAcceptingEntities() {}
@within: 指定匹配必须包括某个注解的的类里的所有连接点
@within(org.springframework.stereotype.Repository)
@annotation: 匹配那些有指定注解的连接点
@annotation(org.springframework.stereotype.Repository)
bean: 用于匹配指定Bean实例内的连接点,传入bean的id或name,支持使用*通配符

切点表达式组合
使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系
execution(* com.cnblogs.hellxz.test..(…)) && args(arg0, arg1)

### SolidWorks 相关资料与教程 对于希望学习和深入理解 SolidWorks 的用户来说,获取高质量的学习资源至关重要。以下是一些关于 SolidWorks 教程及相关资源的信息: #### 官方与社区支持 官方文档和技术支持通常是了解软件的最佳起点。SolidWorks 提供了详尽的帮助文件以及在线培训课程[^1]。这些资源不仅涵盖了基础知识,还提供了高级技巧的教学。 #### 开放资源库 有一个开放的项目地址可以访问到一套全面的 SolidWorks 学习材料,该项目包含了从基础操作到复杂建模的各种指南,适合不同层次的学习者使用。通过此链接可以直接进入该资源页面:https://gitcode.com/open-source-toolkit/b058a 。这里的内容可以帮助快速上手并熟练运用 SolidWorks 进行产品设计和开发工作。 #### 工程图的重要性及其应用 除了三维模型创建外,在制造业中非常重要的环节就是工程图纸制作。正如所提到,SolidWorks 中集成的强大工程图功能几乎完全可以替代传统 CAD 软件如 AutoCAD 来完成这项任务[^2]。它允许设计师定义详细的尺寸规格,包括但不限于尺寸公差、形状位置偏差控制(SPC)参数设定等要素,这些都是制造过程中不可或缺的部分. #### 功能概述 为了更好地利用这款强大的工具来满足不同的需求场景,SolidWorks 设计了几大核心模块分别针对草绘绘制(直线/曲线),实体构建(拉伸特征命令),组件组装管理以及最终输出平面视图这几个方面进行了划分说明如下所示: - **草图**: 包含基本几何图形绘制选项比如线条画法. - **零件**: 支持基于先前建立好的轮廓扩展形成具体物理对象实例化过程中的各种变形处理方法论探讨. - **装配体**: 实现多部件间相互关联关系的确立机制阐述清楚如何实现整体结构稳定性的保障措施制定原则介绍. - **工程图**: 将立体形态转换成适用于车间生产的二维表达形式的同时加入必要注解标记等内容补充完善整个流程链条闭环建设目标达成情况评估标准确立依据参考资料列举出处标明编号对应关系梳理清晰明了便于后续查阅核实确认无误后再做进一步推广普及应用实践检验效果反馈收集整理分析总结经验教训吸取改进提升效率质量水平持续优化迭代更新版本保持竞争力领先优势地位稳固发展态势良好前景广阔未来可期充满信心期待更多惊喜呈现给大家共同见证成长历程分享喜悦成果共创辉煌明天共同努力奋斗拼搏成就伟大梦想追求卓越品质树立行业标杆引领潮流风尚成为时代先锋模范代表人物载入史册永垂不朽流芳百世万代敬仰怀念不忘初衷使命担当责任重于泰山不敢丝毫懈怠松劲坚持到底勇往直前不断超越自我突破极限挑战未知领域探索无限可能性空间拓展人类认知边界贡献智慧力量推动社会进步文明进程加速前行步伐迎接更加美好的新时代到来吧朋友们让我们携手同行一起创造属于我们的传奇故事书写灿烂篇章留下永恒印记铭刻岁月痕迹记录珍贵瞬间定格美好时光永远珍藏心底深处最柔软的地方温暖彼此陪伴一生一世永不分离分隔两地天涯海角心连着心紧紧相依偎直到地老天荒宇宙尽头依然守候在一起好吗?[^3] ```python # 示例代码展示如何加载 SolidWorks 应用程序接口 (API) import win32com.client def launch_solidworks(): try: swApp = win32com.client.Dispatch("SldWorks.Application") # 启动 SolidWorks API return swApp except Exception as e: print(f"Error launching SolidWorks: {e}") return None if __name__ == "__main__": app = launch_solidworks() if app is not None: print("SolidWorks has been successfully launched via Python.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值