基于 XML 的 AOP 配置

本文详细介绍了Spring框架中基于XML的AOP配置方法,包括导入jar包、创建配置文件、配置切面、通知类型及切入点表达式等内容。通过具体代码示例,阐述了如何在业务逻辑中应用前置、后置、异常、最终和环绕通知。

基于 XML 的 AOP 配置

	1: 导入jar包  pom.xml
		<?xml version="1.0" encoding="UTF-8"?>
		<project xmlns="http://maven.apache.org/POM/4.0.0"
		         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
		    <modelVersion>4.0.0</modelVersion>

		    <groupId>com.demos</groupId>
		    <artifactId>day03_eesy_03springAOP</artifactId>
		    <version>1.0-SNAPSHOT</version>
		    <packaging>jar</packaging>

		    <dependencies>
		        <dependency>
		            <groupId>org.springframework</groupId>
		            <artifactId>spring-context</artifactId>
		            <version>5.0.2.RELEASE</version>
		        </dependency>

		        <dependency>
		            <groupId>org.aspectj</groupId>
		            <artifactId>aspectjweaver</artifactId>
		            <version>1.8.7</version>
		        </dependency>
		    </dependencies>
		</project>
	2: 创建 spring 的配置文件并导入约束
		* 此处导入aop配置 bean.xml

			<?xml version="1.0" encoding="UTF-8"?>
			<beans xmlns="http://www.springframework.org/schema/beans"
		        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		        xmlns:aop="http://www.springframework.org/schema/aop"
		        xsi:schemaLocation="http://www.springframework.org/schema/beans
		        http://www.springframework.org/schema/beans/spring-beans.xsd
		        http://www.springframework.org/schema/aop
		        http://www.springframework.org/schema/aop/spring-aop.xsd">

			    <!-- 配置srping的Ioc,把service对象配置进来-->
			    <bean id="accountService" class="com.demos.service.impl.AccountServiceImpl">
			    </bean>

			    <!--spring中基于XML的AOP配置步骤
			        1、把通知Bean也交给spring来管理
			        2、使用aop:config标签表明开始AOP的配置
			        3、使用aop:aspect标签表明配置切面
			                id属性:是给切面提供一个唯一标识
			                ref属性:是指定通知类bean的Id。
			        4、在aop:aspect标签的内部使用对应标签来配置通知的类型
			               我们现在示例是让printLog方法在切入点方法执行之前之前:所以是前置通知
			               aop:before:表示配置前置通知
			                    method属性:用于指定Logger类中哪个方法是前置通知
			                    pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强
			    -->

			    <!-- 配置Logger类 -->
			    <bean id="logger" class="com.demos.utils.Logger"></bean>

			    <!--配置AOP-->
			    <aop:config>
			        <!--配置切面 -->
			        <aop:aspect id="logAdvice" ref="logger">
			            <!-- 配置通知的类型,并且建立通知方法和切入点方法的关联-->
			            <aop:before method="printLog" 
			            	pointcut="execution(* com.demos.service.impl.*.*(..))">
			            </aop:before>
			        </aop:aspect>
			    </aop:config>

			</beans>

		1 第一步:把通知类用 bean 标签配置起来
			<!-- 配置srping的Ioc,把service对象配置进来-->
				<bean id="accountService" class="com.demos.service.impl.AccountServiceImpl">
			</bean>
		2 第二步:使用 aop:config 声明 aop 配置
			aop:config:
				作用:用于声明开始 aop 的配置
			<aop:config>
				<!-- 配置的代码都写在此处 -->
			</aop:config>
		3 第三步:使用 aop:aspect 配置切面
			aop:aspect:
				作用:
					用于配置切面。
			属性:
				id:给切面提供一个唯一标识。
				ref:引用配置好的通知类 bean 的 id。 
			<aop:aspect id="txAdvice" ref="txManager">
				<!--配置通知的类型要写在此处-->
			</aop:aspect>
		4 第四步:使用 aop:pointcut 配置切入点表达式
			作用:
				用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。
			属性:
				expression:用于定义切入点表达式。
				id:用于给切入点表达式提供一个唯一标识
			<aop:pointcut expression="execution(
				public void com.demos.service.impl.AccountServiceImpl.transfer(
				java.lang.String, java.lang.String, java.lang.Float) )" id="pt1"/>
		5 第五步:使用 aop:xxx 配置对应的通知类型
			* aop:before
				作用:
					用于配置前置通知。指定增强的方法在切入点方法(目标方法)之前执行
				属性:
					method:用于指定通知类中的增强方法名称
					ponitcut-ref:用于指定切入点的表达式的引用
					poinitcut:用于指定切入点表达式
				执行时间点:
					切入点方法执行之前执行

				<aop:before method="beginTransaction" pointcut-ref="pt1"/>
			* aop:after-returning
				作用:
					用于配置后置通知,在目标方法之后执行,可以获取目标方法的返回值
				属性:
					method:指定通知中方法的名称。
					pointct:定义切入点表达式
					pointcut-ref:指定切入点表达式的引用
					returning: 获取返回值
				执行时间点:
					切入点方法正常执行之后。它和异常通知只能有一个执行

				<aop:after-returning method="commit" pointcut-ref="pt1"/>
			* aop:after-throwing
				作用:
					用于配置异常通知
				属性:
					method:指定通知中方法的名称。
					pointct:定义切入点表达式
					pointcut-ref:指定切入点表达式的引用
					throwing:获得异常
				执行时间点:
					切入点方法执行产生异常后执行。它和后置通知只能执行一个

				<aop:after-throwing method="rollback" pointcut-ref="pt1"/>
			* aop:after
				作用:
					用于配置最终通知
				属性:
					method:指定通知中方法的名称。
					pointct:定义切入点表达式
					pointcut-ref:指定切入点表达式的引用
				执行时间点:
					无论切入点方法执行时是否有异常,它都会在其后面执行。

				<aop:after method="release" pointcut-ref="pt1"/>

			* 配置
				<!--配置AOP-->
			    <aop:config>
			        <!-- 配置切入点表达式 id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容
			              此标签写在aop:aspect标签内部只能当前切面使用。
			              它还可以写在aop:aspect外面,此时就变成了所有切面可用,只能在aop:aspect之前配置,否则报错
			          -->
			        <aop:pointcut id="pt1" 
			        	expression="execution(* com.demos.service.impl.*.*(..))">
			        </aop:pointcut>

			        <!--配置切面 -->
			        <aop:aspect id="logAdvice" ref="logger">
			            <!-- 配置前置通知:在切入点方法执行之前执行
			            <aop:before method="beforePrintLog" pointcut-ref="pt1" >
			            </aop:before>-->

			            <!-- 配置后置通知:在切入点方法正常执行之后值。它和异常通知永远只能执行一个
			            <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1">
			            </aop:after-returning>-->

			            <!-- 配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个-->
			            <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1">
			            </aop:after-throwing>-->

			            <!-- 配置最终通知:无论切入点方法是否正常执行它都会在其后面执行-->
			            <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>

			            <!-- 配置环绕通知 详细的注释请看Logger类中 -->
			            <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
			        </aop:aspect>
			    </aop:config>

	3: 切入点表达式说明
        关键字:execution(表达式)
        表达式:
            访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)
        标准的表达式写法:
            public void com.demos.service.impl.AccountServiceImpl.saveAccount()
        访问修饰符可以省略
            void com.demos.service.impl.AccountServiceImpl.saveAccount()
        返回值可以使用通配符,表示任意返回值
            * com.demos.service.impl.AccountServiceImpl.saveAccount()
        包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.
            * *.*.*.*.AccountServiceImpl.saveAccount())
        包名可以使用..表示当前包及其子包
            * *..AccountServiceImpl.saveAccount()
        类名和方法名都可以使用*来实现通配
            * *..*.*()
        参数列表:
            可以直接写数据类型:
                基本类型直接写名称           int
                引用类型写包名.类名的方式   java.lang.String
            可以使用通配符表示任意类型,但是必须有参数
            可以使用..表示有无参数均可,有参数可以是任意类型
        全通配写法:
            * *..*.*(..)

        实际开发中切入点表达式的通常写法:
            切到业务层实现类下的所有方法
                * com.demos.service.impl.*.*(..)

            <!--配置AOP-->
		    <aop:config>
		        <!--配置切面 -->
		        <aop:aspect id="logAdvice" ref="logger">
		            <!-- 配置通知的类型,并且建立通知方法和切入点方法的关联-->
		            <aop:before method="printLog" 
		            	pointcut="execution(* com.demos.service.impl.*.*(..))">
		            </aop:before>
		        </aop:aspect>
		    </aop:config>
    4: 环绕通知
    	/**
	     * 环绕通知
	     * 问题:
	     *      当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。
	     * 分析:
	     *      通过对比动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。
	     * 解决:
	     *      Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。
	     *      该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。
	     *
	     * spring中的环绕通知:
	     *      它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。
	     */
	    public Object aroundPringLog(ProceedingJoinPoint pjp){
	        Object rtValue = null;
	        try{
	            Object[] args = pjp.getArgs();//得到方法执行所需的参数

	            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");

	            rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)

	            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");

	            return rtValue;
	        }catch (Throwable t){
	            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");
	            throw new RuntimeException(t);
	        }finally {
	            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
	        }
	    }

		aop:around:
			作用:
				用于配置环绕通知
			属性:
				method:指定通知中方法的名称。
				pointct:定义切入点表达式
				pointcut-ref:指定切入点表达式的引用
			说明:
				它是 spring 框架为我们提供的一种可以在代码中手动控制增强代码什么时候执行的方式。
			注意:
				通常情况下,环绕通知都是独立使用的
				spring 框架为我们提供了一个接口:ProceedingJoinPoint,它可以作为环绕通知的方法参数。在环绕通知执行时,spring 框架会为我们提供该接口的实现类对象,我们直接使用就行。
	5: 综合案例
		* UserService.java
			package com.demos.aop_xml;

			public interface UserService {
			   public void save(String name,int id);
			   public String getById(int id);
			}
		* UserServiceImpl.java
			package com.demos.aop_xml;

			public class UserServiceImpl implements UserService {

				@Override
				public void save(String name,int id) {
					// TODO Auto-generated method stub
			        System.out.println("保存用户。。。");
			        //int i=1/0;
				}

				@Override
				public String getById(int id) {
					// TODO Auto-generated method stub
					System.out.println("根据主键获取用户。。。");
					return "小强";
				}
			}
		* ServiceProxy.java
			package com.demos.aop_xml;

			import org.aspectj.lang.JoinPoint;
			import org.aspectj.lang.ProceedingJoinPoint;

			//代理类
			public class ServiceProxy {
				//JoinPoint封装了目标类中方法的特性(方法名,参数等。)
				public void toStrong(JoinPoint jp/*,Object res*//*,Throwable exp*/) {
					//目标类的中切点的参数
					String methodname = jp.getSignature().getName();
					System.out.println("目标方法名:"+methodname);
					if ("save".equals(methodname)) {
						Object[] args = jp.getArgs();
						for (Object o : args) {
							System.out.println("目标方法的参数:"+o);
						}
						System.out.println("增强的内容。。。");
					}
				}
				
				//环绕通知
				public void toStrong1(ProceedingJoinPoint jp) {
					//目标类的中切点的参数
					String methodname = jp.getSignature().getName();
					System.out.println("目标方法名11:"+methodname);
					if ("save".equals(methodname)) {
						Object[] args = jp.getArgs();
						for (Object o : args) {
							System.out.println("目标方法的参数11:"+o);
						}
						System.out.println("增强的内容11。。。");
					}
					System.out.println("开启事务");
					try {
						jp.proceed();//调用目标方法
					}catch (Throwable e) {
						e.printStackTrace();
					}
					System.out.println("提交事务");
				}
			}
		* beans.xml
			<?xml version="1.0" encoding="UTF-8"?>
			<beans xmlns="http://www.springframework.org/schema/beans"
			       xmlns:context="http://www.springframework.org/schema/context"
			       xmlns:aop="http://www.springframework.org/schema/aop"
				   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
				         xsi:schemaLocation="http://www.springframework.org/schema/beans
			                                 http://www.springframework.org/schema/beans/spring-beans.xsd
			                                 http://www.springframework.org/schema/context
			                                 http://www.springframework.org/schema/context/spring-context.xsd
			                                 http://www.springframework.org/schema/aop
			                                 http://www.springframework.org/schema/aop/spring-aop.xsd"
			                                 >
				<!-- 实例化目标类 -->
				<bean id="us" class="com.demos.aop_xml.UserServiceImpl"></bean>
				<!-- 实例化代理类 -->
				<bean id="myproxy" class="com.demos.aop_xml.ServiceProxy"></bean>
				<!-- springaop完成织入 -->
				<aop:config>
					<aop:aspect ref="myproxy">
						<!-- expression:设置切点     访问修饰符  返回值 方法名(参数) -->
						<aop:pointcut expression="execution(* com.demos.aop_xml.*.*(..))" id="pid"/>
						<!-- 前置通知:增强的方法是在目标方法之前执行 -->
						<aop:before method="toStrong" pointcut-ref="pid"/>
						
						<!--后置通知:增强的方法是在目标方法之后执行,当目标方法遇到异常时,通知不会执行  -->
				    	<!--  <aop:after-returning method="toStrong" pointcut-ref="pid" returning="res"/> -->
				    
				    	<!--最终通知:增强的方法是在目标方法之后执行,不论目标方法中是否有异常,通知都会执行  -->
				     	<!-- <aop:after method="toStrong" pointcut-ref="pid"/> -->
				    	
				    	<!-- 异常通知:在目标方法遇到异常时才会执行增强的内容 -->
				    	<!-- <aop:after-throwing method="toStrong" pointcut-ref="pid" throwing="exp"/> -->
				     	
				     	<!-- 环绕通知:可以定义增强的内容在目标方法之前执行或者之后或者前后都执行 -->
				    	<aop:around method="toStrong1" pointcut-ref="pid"/>
					</aop:aspect>
				</aop:config>
			</beans>
		* ProxyTest.java
			package com.demos.aop_xml;

			import org.springframework.context.ApplicationContext;
			import org.springframework.context.support.ClassPathXmlApplicationContext;

			public class ProxyTest {
				public static void main(String[] args) {
					ApplicationContext ap= new ClassPathXmlApplicationContext("com/demos/aop_xml/beans.xml");
					UserService us = ap.getBean("us",UserService.class);
					us.save("来来来",888);
					System.out.println("=====================================");
					us.getById(1);
				}
			}
AI 代码审查Review工具 是一个旨在自动化代码审查流程的工具。它通过集成版本控制系统(如 GitHub 和 GitLab)的 Webhook,利用大型语言模型(LLM)对代码变更进行分析,并将审查意见反馈到相应的 Pull Request 或 Merge Request 中。此外,它还支持将审查结果通知到企业微信等通讯工具。 一个基于 LLM 的自动化代码审查助手。通过 GitHub/GitLab Webhook 监听 PR/MR 变更,调用 AI 分析代码,并将审查意见自动评论到 PR/MR,同时支持多种通知渠道。 主要功能 多平台支持: 集成 GitHub 和 GitLab Webhook,监听 Pull Request / Merge Request 事件。 智能审查模式: 详细审查 (/github_webhook, /gitlab_webhook): AI 对每个变更文件进行分析,旨在找出具体问题。审查意见会以结构化的形式(例如,定位到特定代码行、问题分类、严重程度、分析和建议)逐条评论到 PR/MR。AI 模型会输出 JSON 格式的分析结果,系统再将其转换为多条独立的评论。 通用审查 (/github_webhook_general, /gitlab_webhook_general): AI 对每个变更文件进行整体性分析,并为每个文件生成一个 Markdown 格式的总结性评论。 自动化流程: 自动将 AI 审查意见(详细模式下为多条,通用模式下为每个文件一条)发布到 PR/MR。 在所有文件审查完毕后,自动在 PR/MR 中发布一条总结性评论。 即便 AI 未发现任何值得报告的问题,也会发布相应的友好提示和总结评论。 异步处理审查任务,快速响应 Webhook。 通过 Redis 防止对同一 Commit 的重复审查。 灵活配置: 通过环境变量设置基
【直流微电网】径向直流微电网的状态空间建模与线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模与线性化方法,重点提出了一种基于耦合DC-DC变换器的状态空间平均模型的建模策略。该方法通过数学建模手段对直流微电网系统进行精确的状态空间描述,并对其进行线性化处理,以便于系统稳定性分析与控制器设计。文中结合Matlab代码实现,展示了建模与仿真过程,有助于研究人员理解和复现相关技术,推动直流微电网系统的动态性能研究与工程应用。; 适合人群:具备电力电子、电力系统或自动化等相关背景,熟悉Matlab/Simulink仿真工具,从事新能源、微电网或智能电网研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网的动态建模方法;②学习DC-DC变换器在耦合条件下的状态空间平均建模技巧;③实现系统的线性化分析并支持后续控制器设计(如电压稳定控制、功率分配等);④为科研论文撰写、项目仿真验证提供技术支持与代码参考。; 阅读建议:建议读者结合Matlab代码逐步实践建模流程,重点关注状态变量选取、平均化处理和线性化推导过程,同时可扩展应用于更复杂的直流微电网拓扑结构中,提升系统分析与设计能力。
内容概要:本文介绍了基于物PINN驱动的三维声波波动方程求解(Matlab代码实现)理信息神经网络(PINN)求解三维声波波动方程的Matlab代码实现方法,展示了如何利用PINN技术在无需大量标注数据的情况下,结合物理定律约束进行偏微分方程的数值求解。该方法将神经网络与物理方程深度融合,适用于复杂波动问题的建模与仿真,并提供了完整的Matlab实现方案,便于科研人员理解和复现。此外,文档还列举了多个相关科研方向和技术服务内容,涵盖智能优化算法、机器学习、信号处理、电力系统等多个领域,突出其在科研仿真中的广泛应用价值。; 适合人群:具备一定数学建模基础和Matlab编程能力的研究生、科研人员及工程技术人员,尤其适合从事计算物理、声学仿真、偏微分方程数值解等相关领域的研究人员; 使用场景及目标:①学习并掌握PINN在求解三维声波波动方程中的应用原理与实现方式;②拓展至其他物理系统的建模与仿真,如电磁场、热传导、流体力学等问题;③为科研项目提供可复用的代码框架和技术支持参考; 阅读建议:建议读者结合文中提供的网盘资源下载完整代码,按照目录顺序逐步学习,重点关注PINN网络结构设计、损失函数构建及物理边界条件的嵌入方法,同时可借鉴其他案例提升综合仿真能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值