Flask接口签名sign原理与实例代码浅析
227
2022-12-23
Spring用AspectJ开发AOP(基于Annotation)
基于 Annotation 的声明式
在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关的配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
为此,AspectJ 框架为 AOP 开发提供了另一种开发方式——基于 Annotation 的声明式。AspectJ 允许使用注解定义切面、切入点和增强处理,而 Spring 框架则可以识别并根据这些注解生成 AOP 代理。
关于 Annotation 注解的介绍如表 1 所示。
表 1 Annotation 注解介绍
名称
说明
@Aspect
用于定义一个切面。
@Before
用于定义前置通知,相当于 BeforeAdvice。
@AfterReturning
用于定义后置通知,相当于 AfterReturningAdhttp://vice。
@Around
用于定义环绕通知,相当于MethodInterceptor。
@AfterThrowing
用于定义抛出通知,相当于ThrowAdvice。
@After
用于定义最终final通知,不管是否异常,该通知都会执行。
@DeclareParents
用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。
下面使用注解的方式重新实现《基于XML的声明式》部分的功能。
1. 创建切面类 MyAspect
在 src 目录下创建一个名为 com.mengma.aspectj.annotation 的包,在该包下创建一个切面类 MyAspect,如下所示。
package com.mengma.aspectj.annotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//切面类
@Aspect
@Component
public class MyAspect {
// 用于取代: // expression="execution(*com.mengma.dao..*.*(..))" id="myPointCut"/> // 要求:方法必须是private,没有值,名称自定义,没有参数 @Pointcut("execution(*com.mengma.dao..*.*(..))") private void myPointCut() { } // 前置通知 @Before("myPointCut()") public void myBefore(JoinPoint joinPoint) { System.out.print("前置通知,目标:"); System.out.print(joinPoint.getTarget() + "方法名称:"); System.out.println(joinPoint.getSignature().getName()); } // 后置通知 @AfterReturning(value = "myPointCut()") public void myAfterReturning(JoinPoint joinPoint) { System.out.print("后置通知,方法名称:" + joinPoint.getSignature().getName()); } // 环绕通知 @Around("myPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕开始"); // 开始 Object obj = proceedingJoinPoint.proceed(); // 执行当前目标方法 System.out.println("环绕结束"); // 结束 return obj; } // 异常通知 @AfterThrowing(value = "myPointCut()", throwing = "e") public void myAfterThrowing(JoinPoint joinPoint, Throwable e) { System.out.println("异常通知" + "出错了" + e.getMessage()); } // 最终通知 @After("myPointCut()") public void myAfter() { System.out.println("最终通知"); } } 上述代码中,第 13 行 @Aspect 注解用于声明这是一个切面类,该类作为组件使用,所以要添加 @Component 注解才能生效。第 19 行中 @Poincut 注解用于配置切入点,取代 XML 文件中配置切入点的代码。 在每个通知相应的方法上都添加了注解声明,并且将切入点方法名“myPointCut”作为参数传递给要执行的方法,如需其他参数(如异常通知的异常参数),可以根据代码提示传递相应的属性值。 2. 为目标类添加注解 在 com.mengma.dao.CustomerDaoImpl 目标类中添加注解 @Repository("customerDao")。 import org.springframework.stereotype.Repository; @Repository("customerDao") public class CustomerDao { public void doSome(){ // int i=1/0; System.out.println("正式业务"); } } 3. 创建Spring配置文件 在 com.mengma.aspectj.annotation 包下创建 applicationContext.xml 配置文件,如下所示。 xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:aop="http://springframework.org/schema/aop" xmlns:context="http://springframework.org/schema/context" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans-2.5.xsd http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop-2.5.xsd http://springframework.org/schema/context http://springframework.org/schema/context/spring-context.xsd"> 上述代码中,首先导入了 AOP 命名空间及其配套的约束,使切面类中的 @AspectJ 注解能够正常工作;第 13 行代码添加了扫描包,使注解生效。需要注意的是,这里还包括目标类 com.mengma.dao.CustomerDaoImpl 的注解,所以 base-package 的值为 com.mengma;第 15 行代码的作用是切面开启自动代理。 4. 创建测试类 在 com.mengma.aspectj.annotation 包下创建一个名为 AnnotationTest 的测试类,如下所示。 package com.mengma.aspectj.annotation; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mengma.dao.CustomerDao; public class AnnotationTest { @Test public void test() { String xmlPath = "com/mengma/aspectj/xml/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext( xmlPath); // 从spring容器获取实例 CustomerDao customerDao = (CustomerDao) applicationContext .getBean("customerDao"); // 执行方法 customerDao.add(); } } 5. 运行项目并查看结果 使用 JUnit 测试运行 test() 方法,运行成功后,控制台的输出结果如图 3 所示。 图 3 运行结果 删除 add() 方法中的“int i=1/0;”,重新运行 test() 方法,此时控制台的输出结果如图 4 所示。 图 4 运行结果 从图 3 和图 4 的输出结果中可以看出,已成功使用 Annotation 的方式实现了 AOP 开发。与其他方式相比,基于 Annotation 方式实现 AOP 的效果是最方便的方式,所以实际开发中推荐使用注解的方式。
// expression="execution(*com.mengma.dao..*.*(..))" id="myPointCut"/>
// 要求:方法必须是private,没有值,名称自定义,没有参数
@Pointcut("execution(*com.mengma.dao..*.*(..))")
private void myPointCut() {
}
// 前置通知
@Before("myPointCut()")
public void myBefore(JoinPoint joinPoint) {
System.out.print("前置通知,目标:");
System.out.print(joinPoint.getTarget() + "方法名称:");
System.out.println(joinPoint.getSignature().getName());
}
// 后置通知
@AfterReturning(value = "myPointCut()")
public void myAfterReturning(JoinPoint joinPoint) {
System.out.print("后置通知,方法名称:" + joinPoint.getSignature().getName());
}
// 环绕通知
@Around("myPointCut()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint)
throws Throwable {
System.out.println("环绕开始"); // 开始
Object obj = proceedingJoinPoint.proceed(); // 执行当前目标方法
System.out.println("环绕结束"); // 结束
return obj;
}
// 异常通知
@AfterThrowing(value = "myPointCut()", throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("异常通知" + "出错了" + e.getMessage());
}
// 最终通知
@After("myPointCut()")
public void myAfter() {
System.out.println("最终通知");
}
}
上述代码中,第 13 行 @Aspect 注解用于声明这是一个切面类,该类作为组件使用,所以要添加 @Component 注解才能生效。第 19 行中 @Poincut 注解用于配置切入点,取代 XML 文件中配置切入点的代码。
在每个通知相应的方法上都添加了注解声明,并且将切入点方法名“myPointCut”作为参数传递给要执行的方法,如需其他参数(如异常通知的异常参数),可以根据代码提示传递相应的属性值。
2. 为目标类添加注解
在 com.mengma.dao.CustomerDaoImpl 目标类中添加注解 @Repository("customerDao")。
import org.springframework.stereotype.Repository;
@Repository("customerDao")
public class CustomerDao {
public void doSome(){
// int i=1/0;
System.out.println("正式业务");
}
}
3. 创建Spring配置文件
在 com.mengma.aspectj.annotation 包下创建 applicationContext.xml 配置文件,如下所示。
xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:aop="http://springframework.org/schema/aop" xmlns:context="http://springframework.org/schema/context" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans-2.5.xsd http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop-2.5.xsd http://springframework.org/schema/context http://springframework.org/schema/context/spring-context.xsd">
xmlns:xsi="http://w3.org/2001/XMLSchema-instance"
xmlns:aop="http://springframework.org/schema/aop"
xmlns:context="http://springframework.org/schema/context"
xsi:schemaLocation="http://springframework.org/schema/beans
http://springframework.org/schema/beans/spring-beans-2.5.xsd
http://springframework.org/schema/aop
http://springframework.org/schema/aop/spring-aop-2.5.xsd
http://springframework.org/schema/context
http://springframework.org/schema/context/spring-context.xsd">
上述代码中,首先导入了 AOP 命名空间及其配套的约束,使切面类中的 @AspectJ 注解能够正常工作;第 13 行代码添加了扫描包,使注解生效。需要注意的是,这里还包括目标类 com.mengma.dao.CustomerDaoImpl 的注解,所以 base-package 的值为 com.mengma;第 15 行代码的作用是切面开启自动代理。
4. 创建测试类
在 com.mengma.aspectj.annotation 包下创建一个名为 AnnotationTest 的测试类,如下所示。
package com.mengma.aspectj.annotation;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mengma.dao.CustomerDao;
public class AnnotationTest {
@Test
public void test() {
String xmlPath = "com/mengma/aspectj/xml/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
xmlPath);
// 从spring容器获取实例
CustomerDao customerDao = (CustomerDao) applicationContext
.getBean("customerDao");
// 执行方法
customerDao.add();
}
}
5. 运行项目并查看结果
使用 JUnit 测试运行 test() 方法,运行成功后,控制台的输出结果如图 3 所示。
图 3 运行结果
删除 add() 方法中的“int i=1/0;”,重新运行 test() 方法,此时控制台的输出结果如图 4 所示。
图 4 运行结果
从图 3 和图 4 的输出结果中可以看出,已成功使用 Annotation 的方式实现了 AOP 开发。与其他方式相比,基于 Annotation 方式实现 AOP 的效果是最方便的方式,所以实际开发中推荐使用注解的方式。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~