本篇博文用一个稍复杂点的案例来对比一下基于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编程比较的更多相关文章

  1. Spring学习之旅(七)--SpringMVC视图

    在之前的实例中我们只是在 Controller 中返回了 home 字符类型的值,而没有直接生成可以在浏览器中直接渲染的 HTML,这是因为 SpringMVC 将请求处理的逻辑和视图渲染的实现进行了 ...

  2. Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探

    由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...

  3. spring基于xml的声明式事务控制配置步骤

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  4. Spring学习笔记(七)模拟实际开发过程的调用过程XML版-Setter方式注入

    模拟实际开发过程的调用过程XML版-Setter方式注入 源码获取github [TOC] 1.项目结构 2.jar包跟上个一样 3.重写set方法 UserServiceImpl.java 1234 ...

  5. Spring学习之旅(六)Spring AOP工作原理初探

    AOP(Aspect-Oriented  Programming,面向切面编程)是Spring提供的关键技术之一. AOP基于IoC,是对OOP(Object-Oriented Programming ...

  6. Spring学习之旅(五)--AOP

    什么是 AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是 OOP(Object-Oriented Programing,面向对象编程)的补充和完善. OO ...

  7. spring 基于XML的申明式AspectJ通知的执行顺序

    spring 基于XML的申明式AspectJ通知的执行顺序 关于各种通知的执行顺序,结论:与配置文件中的申明顺序有关 1. XML文件配置说明 图片来源:<Java EE企业级应用开发教程&g ...

  8. spring学习笔记(七)HttpMessageConverter

    spring学习笔记(七)HttpMessageConverter 1. HttpMessageConverter的加载 2. 从StringMessageConverter探究消息转换器的原理 1. ...

  9. Spring学习之旅(十)--MockMvc

    在之前的 Spring学习之旅(八)--SpringMVC请求参数 我们是通过在控制台输出来验证参数是否正确,但是这样做实在是太耗时间了,我们今天来学习下 MockMvc,它可以让我们不需要启动项目就 ...

随机推荐

  1. linux目录跳转快捷方式——z武器

    z是一个shell脚本,可以帮你快速的切换目录.至于是什么原理我还没有深究,有兴趣的东西可以看下. z的源码在这里:https://github.com/rupa/z/blob/master/z.sh ...

  2. Testing - 敏捷测试

    敏捷测试(Agile Testing) SM= Scrum Master PO= Product Owner PB= Product Backlog SB= Sprint Backlog Scrum ...

  3. yii学习笔记--url解析

    在通过yiic命令生成了一个app之后,我们通过浏览器访问会看到这样的一个页面.   点击home时,url为:http://localhost/blog/index.php?r=site/index ...

  4. python自动化工具之pywinauto(一个实例)结合pyuserinput

    以下是pywinauto使用指南.这个窗口句柄可以在Spy++中查看 (Microsoft Spy++(查看窗口句柄) 10.00.30319 官方最新绿色版) python自动化工具之pywinau ...

  5. [java] 为什么重写equals()必须要重写hashCode()

    本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 在Java API文档中关于hashCode方法有以下几点规定(原文来自java深入解析一书) 1 在j ...

  6. 设置Firefox(火狐)浏览器的中文菜单/界面

    步骤一: 设置Firefox浏览器的中文菜单/界面.首先需要查一下正在使用的火狐版本号(小生使用的火狐版本是55.0.3).      步骤二: 下载对应版本的xpi中文插件 其次,访问下面的火狐官方 ...

  7. Vc数据库编程基础MySql数据库的表增删改查数据

    Vc数据库编程基础MySql数据库的表增删改查数据 一丶表操作命令 1.查看表中所有数据 select * from 表名 2.为表中所有的字段添加数据 insert into 表名( 字段1,字段2 ...

  8. 三大主流软件负载均衡器对比(LVS VS Nginx VS Haproxy)

    LVS:1.抗负载能力强.抗负载能力强.性能高,能达到F5硬件的60%:对内存和cpu资源消耗比较低2.工作在网络4层,通过vrrp协议转发(仅作分发之用),具体的流量由linux内核处理,因此没有流 ...

  9. sql server 获取自增列下一个值或者获取指定表的主键值

    IDENT_CURRENT('TableName')为当前的最大标识值, IDENT_INCR('TableName')为设置的标识值增量, 两者相加即为下一个标识值 如: SELECT IDENT_ ...

  10. golang高性能RPC:Apache Thrift安装使用完全攻略

    在企业应用中RPC的使用可以说是十分的广泛,使用该技术可以方便的与各种程序交互而不用考虑其编写使用的语言. 如果你对RPC的概念还不太清楚,可以点击这里. 现今市面上已经有许多应用广泛的RPC框架,比 ...