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,它可以让我们不需要启动项目就 ...
随机推荐
- 如何使用 GDB
前期准备 启动GDB方法 设置运行参数 查看源码 断点break 使用 运行程序 查看运行时数据 查看内存数据 分割窗口 问题汇总 参考文献 GDB, The GNU Project debugger ...
- java的四种内部类详解
引言 内部类,嵌套在另一个类的里面,所以也称为:嵌套类; 内部类分为以下四种: 静态内部类 成员内部类 局部内部类 匿名内部类 一.静态内部类 静态内部类: 一般也称"静态嵌套类" ...
- 【ABP框架系列学习】模块系统(4)之插件示例开发
0.引言 上一篇博文主要介绍了ABP模块及插件的相关知识,本章节主要开发一个插件示例来学习如何创建一个插件,并在应用程序中使用.这个命名为FirstABPPlugin的插件主要在指定的时间段内删除审计 ...
- Apache Flume 1.7.0 自定义输入输出
自定义http source config a1.sources.r1.type=http a1.sources.r1.bind=localhost a1.sources.r1.port= a1.so ...
- java.sql.SQLException: The SQL statement must not be null or empty.这个错误
今天发现了这个错误 java.sql.SQLException: The SQL statement must not be null or empty. 并且看了些网页:综合说下这个错误. 一般都是 ...
- Elasticsearch实践(二):搜索
本文以 Elasticsearch 6.2.4为例. 经过前面的基础入门,我们对ES的基本操作也会了.现在来学习ES最强大的部分:全文检索. 准备工作 批量导入数据 先需要准备点数据,然后导入: wg ...
- ABP框架是怎么一回事呢?
ABP(ASP.NET Boilerplate['bɔɪlɚplet]:样板文件),就是一套基于.Net开源框架,官方地址为:https://aspnetboilerplate.com/ , 在这个地 ...
- istio小结
一.概述 测试环境已经跑了很长时间的istio了,也更新到了最新的istio-1.1.性能相较之前提升很大,官方给出的测试数据说是延迟降低到了8ms,但是实际测试确实访问速度有很大的提升,但是确实还是 ...
- JavaScript之函数(上)
在编程语言中,无论是面向过程的C,兼备面过程和对象的c++,还是面向对象的编程语言,如java,.net,php等,函数均扮演着重要的角色.当然,在面向对象编程语言JavaScript中(严格来说,J ...
- 网络扫描工具nmap
nmap一般就用来扫描主机是否在线(特别是扫描局域网内存活的机器).开放了哪些端口.其他的功能用的比较少,做渗透的人可能要了解的多些. 1.1 选项说明 nmap需要自行安装. shell> y ...