Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AOP编程比较
本篇博文用一个稍复杂点的案例来对比一下基于XML配置与基于AspectJ注解配置的AOP编程的不同。
相关引入包等Spring AOP编程准备,请参考小编的其他博文,这里不再赘述。
案例要求:
写一个简单的实现四则运算的计算器。
加入AOP功能:日志功能;检测参数中是否有负数的功能。
废话不多说了,直接上代码:
(一)基于XML配置:
定义了一个接口类:
package com.edu.aop; public interface ArithmeticCalculator { int add(int i,int j);
int sub(int i,int j);
int mul(int i,int j);
int div(int i,int j);
}
实现类:
package com.edu.aop; public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override
public int add(int i, int j) {
return i+j;
} @Override
public int sub(int i, int j) {
return i-j;
} @Override
public int mul(int i, int j) {
return i*j;
} @Override
public int div(int i, int j) {
return i/j;
} }
日志切片类:
package com.edu.aop; import java.util.Arrays; import org.aspectj.lang.JoinPoint; public class LoggingAspect {
/**
* 日志切面类
*/ public void beforeMethod(JoinPoint joinPoint){
//获取方法名
String methodName=joinPoint.getSignature().getName();
//获取方法实参值列表
Object[] args=joinPoint.getArgs();
System.out.println("The method "+methodName+" begin with "+Arrays.asList(args));
} public void afterMethod(JoinPoint joinPoint){
String methodName=joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" ends");
}
}
检测参数中是否有负数的切片类:
package com.edu.aop; import java.util.Arrays; import org.aspectj.lang.JoinPoint; public class ValidationAspect { public void validationArgs(JoinPoint joinPoint){
String methodName=joinPoint.getSignature().getName();
Object[] args=joinPoint.getArgs();
System.out.println("待验证参数:"+Arrays.asList(args));
if(args!=null&&args.length>0){
for(int i=0;i<args.length;++i){
if(((Integer)args[i]).intValue()<0){
System.out.println("警告:方法"+methodName+"()第"+(i+1)+"个参数为负数:"+args[i]);
}
}
}
}
}
xml配置文件applicationContext.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"> <!-- 配置bean -->
<bean id="arithmetic" class="com.edu.aop.ArithmeticCalculatorImpl"></bean> <!-- 分别将切面类声明配置成一个bean -->
<bean id="logging" class="com.edu.aop.LoggingAspect"></bean>
<bean id="validation" class="com.edu.aop.ValidationAspect"></bean> <aop:config>
<!-- 配置日志切片类 -->
<aop:aspect ref="logging" order="2">
<!-- 配置前置通知 及前置通知的切入点-->
<aop:before method="beforeMethod" pointcut="execution(* com.edu.aop.ArithmeticCalculatorImpl.*(..))"></aop:before>
<!-- 配置后置通知及后置通知的切入点 -->
<aop:after method="afterMethod" pointcut="execution(* com.edu.aop.ArithmeticCalculatorImpl.*(..))"></aop:after>
</aop:aspect> <!-- 配置检测参数切片类 -->
<aop:aspect ref="validation" order="1">
<!-- 配置前置通知 及前置通知的切入点-->
<aop:before method="validationArgs" pointcut="execution(* com.edu.aop.ArithmeticCalculatorImpl.*(..))"></aop:before>
</aop:aspect>
</aop:config>
</beans>
主方法检测类:
package com.edu.aop; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext act=new ClassPathXmlApplicationContext("applicationContext.xml");
ArithmeticCalculator arithmetic=(ArithmeticCalculator)act.getBean("arithmetic");
int result=arithmetic.add(10, 20);
System.out.println("result:"+result);
result=arithmetic.div(-36, 4);
System.out.println("result:"+result);
} }
运行结果:
(二)基于AspectJ注解配置的AOP编程:
直接上代码:
接口类定义同上。
xml配置文件applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 自动扫描的包,实现对注解Bean的管理 -->
<context:component-scan base-package="com.edu.aop"></context:component-scan>
<!-- 使Aspect的注解起作用,从而实现:自动为匹配的类生成代理 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
接口实现类:
package com.edu.aop; import org.springframework.stereotype.Component; //@Component 注解Bean,并设定其名称为arithmetic
@Component("arithmetic")
public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override
public int add(int i, int j) {
return i+j;
} @Override
public int sub(int i, int j) {
return i-j;
} @Override
public int mul(int i, int j) {
return i*j;
} @Override
public int div(int i, int j) {
return i/j;
} }
日志切片类:
package com.edu.aop; import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; //注释声明切面,切面的名称为默认名称(loggingAspect)(即类名首字母小写)
@Order(2) //注释切面的优先级别,数字越小,级别越高
@Aspect //@Aspect 注解声明该Bean是个切面
@Component //@Component 注解Bean,默认名称为loggingAspect
public class LoggingAspect {
/**
* 日志切面类
*/
//注释“前置通知”及其切入点
@Before("execution(public int com.edu.aop.ArithmeticCalculator.add(int,int))")
public void beforeMethod(JoinPoint joinPoint){
//获取方法名
String methodName=joinPoint.getSignature().getName();
//获取方法实参值列表
Object[] args=joinPoint.getArgs();
System.out.println("The method "+methodName+" begin with "+Arrays.asList(args));
} //注解“后置通知”及其切入点
@After("execution(* com.edu.aop.ArithmeticCalculator.*(..))")
public void afterMethod(JoinPoint joinPoint){
String methodName=joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" ends");
}
}
检测参数中是否有负数的切片类:
package com.edu.aop; import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; //注释声明切面,切面的名称为默认名称(loggingAspect)(即类名首字母小写)
@Order(1) //注解切面的优先级别,数字越小,级别越高
@Aspect //注解为一个切面
@Component //注解为一个Bean组件,默认名称为validationAspect
public class ValidationAspect { //注解为前置通知,并注解其切入点表达式
@Before("execution(* com.edu.aop.ArithmeticCalculator.*(..))")
public void validationArgs(JoinPoint joinPoint){
String methodName=joinPoint.getSignature().getName();
Object[] args=joinPoint.getArgs();
System.out.println("待验证参数:"+Arrays.asList(args));
if(args!=null&&args.length>0){
for(int i=0;i<args.length;++i){
if(((Integer)args[i]).intValue()<0){
System.out.println("警告:方法"+methodName+"()第"+(i+1)+"个参数为负数:"+args[i]);
}
}
}
}
}
主方法检测类同上。
运行结果:
由以上案例的两个版本,可以看到两种AOP编程方式在设计思想和设计过程基本一致,只不过,“基于XML的AOP编程”是将配置Bean、切面、通知等操作放在了配置文件中。而“基于AspectJ的AOP编程”则是将这些配置信息放在了源码中,只在配置文件中配置了“AspectJ的注解支持”(即空的<aop:aspectj-autoproxy>元素)和自动扫描的包的支持。
Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AOP编程比较的更多相关文章
- Spring学习之旅(七)--SpringMVC视图
在之前的实例中我们只是在 Controller 中返回了 home 字符类型的值,而没有直接生成可以在浏览器中直接渲染的 HTML,这是因为 SpringMVC 将请求处理的逻辑和视图渲染的实现进行了 ...
- Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探
由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...
- spring基于xml的声明式事务控制配置步骤
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Spring学习笔记(七)模拟实际开发过程的调用过程XML版-Setter方式注入
模拟实际开发过程的调用过程XML版-Setter方式注入 源码获取github [TOC] 1.项目结构 2.jar包跟上个一样 3.重写set方法 UserServiceImpl.java 1234 ...
- Spring学习之旅(六)Spring AOP工作原理初探
AOP(Aspect-Oriented Programming,面向切面编程)是Spring提供的关键技术之一. AOP基于IoC,是对OOP(Object-Oriented Programming ...
- Spring学习之旅(五)--AOP
什么是 AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是 OOP(Object-Oriented Programing,面向对象编程)的补充和完善. OO ...
- spring 基于XML的申明式AspectJ通知的执行顺序
spring 基于XML的申明式AspectJ通知的执行顺序 关于各种通知的执行顺序,结论:与配置文件中的申明顺序有关 1. XML文件配置说明 图片来源:<Java EE企业级应用开发教程&g ...
- spring学习笔记(七)HttpMessageConverter
spring学习笔记(七)HttpMessageConverter 1. HttpMessageConverter的加载 2. 从StringMessageConverter探究消息转换器的原理 1. ...
- Spring学习之旅(十)--MockMvc
在之前的 Spring学习之旅(八)--SpringMVC请求参数 我们是通过在控制台输出来验证参数是否正确,但是这样做实在是太耗时间了,我们今天来学习下 MockMvc,它可以让我们不需要启动项目就 ...
随机推荐
- python读取并写入csv文件
在ubuntu下,新建.csv文件的方法是使用LibreOffice来创建一个数据表,然后我们把表格存储为.csv的格式: “Save as”菜单把我们的表格存为一个CSV的文件格式:命名为csvDa ...
- AI - 框架(Frameworks)
1 - Scikit-Learn Sklearn(scikit-learn: machine learning in Python):https://scikit-learn.org/ 文档丰富而又详 ...
- 【学习笔记】分类算法-k近邻算法
k-近邻算法采用测量不同特征值之间的距离来进行分类. 优点:精度高.对异常值不敏感.无数据输入假定 缺点:计算复杂度高.空间复杂度高 使用数据范围:数值型和标称型 用例子来理解k-近邻算法 电影可以按 ...
- Js中处理日期加减天数
Js的处理日期还是很方便的. 一. 格式化日期为2017-07-04的格式 function formatTime(date) { var year = date.getFullYear(); var ...
- 用javascript写原生ajax(笔记)
AJAX 的全名叫做 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).它最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并 ...
- 【原创】空中鼠标一DMP欧拉角
正在搞六轴传感器,今天移植了MPU6050的MothionDriver的DMP固件到STM32上了,能够稳定地输出欧拉角(也就是俯仰角.航向角.横滚角)和XYZ三轴加速度值,在电脑的上位机模拟了装置的 ...
- Keras 构建DNN 对用户名检测判断是否为非法用户名(从数据预处理到模型在线预测)
一. 数据集的准备与预处理 1 . 收集dataset (大量用户名--包含正常用户名与非法用户名) 包含两个txt文件 legal_name.txt ilegal_name.txt. 如下图所 ...
- datatables 配套bootstrap3样式使用小结(1)
今天介绍汇总一下datatables. 网址: www.datatables.net 公司CMS内容资讯站的后台管理界面用了大量的table来管理数据,试用了之后,感觉挺不错,推荐一下. 先上一个基本 ...
- RNN入门(二)识别验证码
介绍 作为RNN的第二个demo,笔者将会介绍RNN模型在识别验证码方面的应用. 我们的验证码及样本数据集来自于博客: CNN大战验证码,在这篇博客中,我们已经准备好了所需的样本数据集,不需要 ...
- C#操作DbConnection类
一.常用属性 名称 说明 ConnectionString 获取或设置用于打开数据库的字符串.(重写 DbConnection.ConnectionString) ConnectionTimeout ...