Spring与AOP

AOP与AspectJ深入解析

AOP简介

AOP,Aspect Orient Programming,面向切面编程。是一种概念,是一种思想,其实现者很多,Spring就是实现者之一。

AOP是OOP(面向对象编程)的一种补充。OOP是从静态角度考虑程序的结构,而AOP是动态角度考虑程序的运行过程。

Spring用于降低耦合度。IoC用于降低主业务逻辑之间的耦合度;AOP用于降低主业务逻辑与系统级服务(交叉业务逻辑)间的耦合度,将系统级服务在运行时织入到主业务逻辑之中。

Spring的AOP的底层工作原理,是使用动态代理对主业务进行增强。而动态代理使用的是JDK的Proxy与CGLIB两种动态代理。

AOP的知识点:

  • 切面:切面指的就是交叉业务逻辑比如记录日志事务管理等等。就是要对主业务逻辑进行增强的部分。AOP编程常见的切面有两种,一种是通知,一种是顾问
  • 织入:就是将切面切入到主业务逻辑的过程,称为织入。
  • 连接点:可以织入切面的目标方法,称为连接点。
  • 切入点:实际织入切面的目标方法。
  • 目标对象:用于被增强的对象。主业务逻辑所在类的对象
  • 通知:是一种切面,可以完成简单的织入功能。例如:可以指定切入的时间点。是方法执行前还是方法结束前或者执行过程中等等时间点。通知会将目标类中所有的方法作为切入点进行织入。
  • 顾问:也是一种切面,其中包含了通知,可以完成更为复杂的织入功能。可以指定具体切入的类和具体方法
  • 引入:一种切面,在不修改源码的前提下,给目标对象增加新的功能。

AOP编程的环境搭建

  • 导入spring-aop的jar包
  • 导入aop联盟的jar包

通知的具体分类:

  • 前置通知MethodBeforeAdvice:用于在主业务方法执行前进行的操作,实现MethodBeforeAdvice接口并实现接口中的方法
public class MyBeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("执行前置通知-----------------");
	}
}

  • 后置通知AfterReturningAdvice:实现AfterReturningAdvice接口中的通知方法
public class MyAfterAdvice implements AfterReturningAdvice {
    //后置通知可以获取到目标方法的返回值returnValue但是不能修改返回值

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("执行后置通知------------------");
	}
    
}
  • 环绕通知:实现MethodInterceptor接口该接口是AOP联盟提供的,该方法可以调用执行目标方法,可以在目标方法执行前后进行功能增强,也可以修改,目标方法的返回值
public class MyInterceptorAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("方法执行前代码");
		String result = (String) invocation.proceed();
		System.out.println("方法执行后代码");
		return result.toUpperCase();
	}

}
  • 异常通知:自定义通知类实现ThrowsAdvice接口,该接口中没有具体需要实现的方法,通过查看源码可知,有四个方法可以选择性的实现我们一般实现afterThrowing(Exception ex)方法,该方法可以重载,用来匹配不同类型的异常,异常通知会在目标方法发生异常时执行。

通知的织入

  • 在spring容器中(配置文件)注册通知
  • 注册目标对象
  • 使用动态代理工厂Bean生成增强后的代理对象
	<!-- 注册前置通知 -->
	<bean id="beforeAdvice" class="com.lscw.advices.MyBeforeAdvice"/>
	
	<!-- 注册目标方法 -->
	<bean id="myCar" class="com.lscw.car.carImpl" />
	
	<!-- 使用代理工厂生成代理对象 -->
	<bean id="carProxy"  class="org.springframework.aop.framework.ProxyFactoryBean" >
		<!-- 指定目标类 -->
		<property name="targetName" value="myCar" />
		<!-- 指定织入的通知,可以指定多个,我这只指定一个前置通知 -->
		<property name="interceptorNames" value="beforeAdvice" />
	</bean>
  • 从spring容器中获取代理对象调用执行其中的方法得出结果

顾问Advisor:

  • 切入点顾问:用于指定切入点织入的位置,就是说,你要将切面织入到哪个目标方法。
  • 引入顾问:在不修改目标类的前提下,给目标对象增加新的功能。

切入点顾问:

  • 名称匹配方法切入点顾问
  • 正则表达式方法切入点顾问:正则表达式方法切入点顾问中的属性pattern所匹配的是方法的全限定性名称

使用动态代理工厂Bean的缺点:

  1. 从spring中获取的是代理对象而不是目标对象
  2. 每一个目标类都要注册代理对象

默认顾问自动生成器:

Bean名称自动代理生成器:

通过注入属性beanNames和interceptorNames可以指定多个Bean和多个顾问或通知


AspectJ对AOP的实现

AspectJ概述:

  • 什么是AspectJ:AspectJ是一个面向切面的框架,它扩展了Java语言。
    AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
  • AspectJ Spring AOP 之间的关系:

    AspectJ是另外一个框架,与Spring没有任何关系。但,AspectJ与Spring都是AOP的实现者。
    下面要讲述的是:基于Spring环境下的AspectJ对AOP的实现。

AspectJ知识点:

  • AspectJ的通知:前置通知  后置通知  环绕通知  异常通知  最终通知
  • 最终通知:无论是否发生异常都会执行的通知
  • 切入点表达式:使用规范execution(方法返回值 空格 方法的全限定名称 参数列表)

    execution( * com.abc.service.*.*(..)):表示com.abc.service包下的所有方法都是切入点。

    execution( * com.abc.service.*.open*(..)):表示com.abc.service包下的所有以open开头的方法都是切入点。

    execution( * *.service.*.*(..)):表示service包(该service包前只能有一级父包)下的所有方法都是切入点。  

    com.service.ISomeService.doFirst()是匹配的。

    com.abc.service.ISomeService.doFirst()是不匹配的。

    execution( * *..service.*.*(..)):表示service包(该service包前可以有任意级的父包)下的所有方法都是切入点。

    com.service.ISomeService.doFirst()是匹配的。

    com.abc.service.ISomeService.doFirst()也是匹配的

AspectJ的环境搭建:

  • AspectJ的核心jar包
  • spring与AspectJ整合的jar包
  • spring-aop的jar包
  • aop联盟的jar包
  • spring容器中引入对aop的约束
  • 注册aop:aspectJ自动代理生成器

基于注解的AspectJ编程:

  • 注解的介绍:
    @Aspect:该注解作用于类上表示该类为切面类

    @Before:表示前置通知,使用方式:@Before(“execution(“* *..aop15.类名或接口名.方法名(..)”)”)

    @AfterReturning:表示后置通知

    @Arround:环绕通知,定义在该注解下的方法需要添加ProceedingJoinPoint参数

    @AfterThrowing:异常通知,定义了异常注解的方法,应添加Exception参数

    @After:最终通知

    @PointCut:使用了该注解的方法,其方法名可以作为切入点
  • 代码示例:
@Aspect // 表示当前类为切面
public class MyAspect {

	// 前置通知
	@Before("execution(* *..aop15.ISomeService.doFirst(..))")
	public void myBefore() {
		System.out.println("执行前置通知方法");
	}

	// 前置通知
	@Before("execution(* *..aop15.ISomeService.doFirst(..))")
	public void myBefore(JoinPoint jp) {
		System.out.println("执行前置通知方法 jp = " + jp);
	}

	// 后置通知
	@AfterReturning("execution(* *..aop15.ISomeService.doSecond(..))")
	public void myAfterReturning() {
		System.out.println("执行后置通知方法");
	}

	// 后置通知
	// 后置通知可以获取到目标方法的执行结果,但不能改变其值
	@AfterReturning(value = "execution(* *..aop15.ISomeService.doSecond(..))", returning = "result")
	public void myAfterReturning(Object result) {
		System.out.println("执行后置通知方法 result = " + result);
	}

	// 环绕通知
	// 环绕通知不仅可以读取到目标方法的执行结果,还可以改变其值
	@Around("execution(* *..aop15.ISomeService.doSecond(..))")
	public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("执行环绕通知 -- 目标方法执行之前");
		// 执行目标方法
		Object proceed = pjp.proceed();
		System.out.println("执行环绕通知 -- 目标方法执行之后");
		if (proceed != null) {
			proceed = ((String) proceed).toUpperCase();
		}
		return proceed;
	}

	// 异常通知
	@AfterThrowing("execution(* *..aop15.ISomeService.doThird(..))")
	public void myAfterThrowing() {
		System.out.println("执行异常通知方法");
	}
	
	// 异常通知
	@AfterThrowing(value = "doThirdPointcut()", throwing="ex")
	public void myAfterThrowing(Exception ex) {
		System.out.println("执行异常通知方法 ex = " + ex.getMessage());
	}
	
	// 最终通知
	@After("execution(* *..aop15.ISomeService.doThird(..))")
	public void myAfter() {
		System.out.println("执行最终通知方法");
	}
	// 最终通知
	@After("doThirdPointcut()")
	public void myAfter2() {
		System.out.println("执行最终通知方法2");
	}
	
	// 定义切入点
	@Pointcut("execution(* *..aop15.ISomeService.doFirst(..))")
	private void doFirstPointcut(){}
	@Pointcut("execution(* *..aop15.ISomeService.doSecond(..))")
	private void doSecondPointcut(){}
	@Pointcut("execution(* *..aop15.ISomeService.doThird(..))")
	private void doThirdPointcut(){}
}

基于XML的AspectJ编程:

  • 前置通知:
  • 后置通知:
  • 环绕通知:
  • 异常通知:如果带参数需要注册参数类型和参数名

  • 最终通知:

 

 

内容概要:本文详细介绍了一个基于黏菌优化算法(SMA)优化的Transformer-LSTM组合模型在多变量回归预测中的完整项目实例。项目通过融合Transformer的全局特征提取能力LSTM的局部时序建模优势,构建层次化混合模型,并引入SMA算法实现超参数自动寻优,提升模型性能泛化能力。项目涵盖数据预处理、模型设计、训练优化、结果评估、GUI可视化界面开发及工程化部署全流程,配套完整代码目录结构设计,支持端到端自动化建模跨平台应用。; 适合人群:具备一定机器学习深度学习基础,熟悉Python编程PyTorch框架,从事数据科学、人工智能研发或工程落地的相关技术人员,尤其是工作1-3年希望提升模型自动化实战能力的研发人员。; 使用场景及目标:①应用于智能制造、金融风控、智慧医疗、能源管理、气象预测、智能交通等多变量时间序列预测场景;②掌握TransformerLSTM融合建模方法;③学习SMA等群体智能算法在深度学习超参数优化中的实际应用;④实现从数据处理到模型部署的全流程自动化开发。; 阅读建议:建议结合文档中的代码示例GUI实现部分动手实践,重点关注模型架构设计、SMA优化机制训练流程细节,配合可视化分析深入理解模型行为。同时可扩展尝试不同数据集优化算法,提升对复杂时序预测任务的综合把控能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值