Spring AOP AspectJ
本文讲述使用AspectJ框架实现Spring AOP。
再重复一下Spring AOP中的三个概念,
- Advice:向程序内部注入的代码。
- Pointcut:注入Advice的位置,切入点,一般为某方法。
- Advisor:Advice和Pointcut的结合单元,以便将Advice和Pointcut分开实现灵活配置。
AspectJ是基于注释(Annotation)的,所以需要JDK5.0以上的支持。
AspectJ支持的注释类型如下:
- @Before
- @After
- @AfterReturning
- @AfterThrowing
- @Around
首先定义一个简单的bean,CustomerBo实现了接口ICustomerBo
ICustomerBo.java如下:

package com.lei.demo.aop.aspectj;
public interface ICustomerBo {
void addCustomer();
void deleteCustomer();
String AddCustomerReturnValue();
void addCustomerThrowException() throws Exception;
void addCustomerAround(String name);
}

CustomerBo.java如下:

package com.lei.demo.aop.aspectj;
public class CustomerBo implements ICustomerBo {
public void addCustomer() {
System.out.println("addCustomer() is running ...");
}
public void deleteCustomer() {
System.out.println("deleteCustomer() is running ...");
}
public String AddCustomerReturnValue() {
System.out.println("AddCustomerReturnValue() is running ...");
return "abc";
}
public void addCustomerThrowException() throws Exception {
System.out.println("addCustomerThrowException() is running ...");
throw new Exception("Generic Error");
}
public void addCustomerAround(String name) {
System.out.println("addCustomerAround() is running ,args:"+name);
}
}

一、 简单的AspectJ,Advice和Pointcut结合在一起
首先没有引入Pointcut之前,Advice和Pointcut是混在一起的
步骤,只需要两步,如下:
- 创建一个Aspect类
- 配置Spring配置文件
第一步,创建Aspect类
LoggingAspect.java如下:

package com.lei.demo.aop.aspectj; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; @Aspect
public class LoggingAspect { @Before("execution(public * com.lei.demo.aop.aspectj.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinPoint){
System.out.println("logBefore() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
} @After("execution(public * com.lei.demo.aop.aspectj.CustomerBo.deleteCustomer(..))")
public void logAfter(JoinPoint joinPoint){
System.out.println("logAfter() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
}
}

解释:
1. 必须使用@Aspect在LoggingAspect声明之前注释,以便被框架扫描到
2. 此例Advice和Pointcut结合在一起,类中的具体方法logBefore和logAfter即为Advice,是要注入的代码,Advice方法上的表达式为Pointcut表达式,即定义了切入点,上例中@Before注释的表达式代表执行CustomerBo.addCustomer方法时注入logBefore代码。
3. 在LoggingAspect方法上加入@Before或者@After等注释
4. "execution(public * com.lei.demo.aop.aspectj.CustomerBo.addCustomer(..))"是Aspect的切入点表达式,其中,*代表返回类型,后边的就要定义要拦截的方法名,这里写的的是com.lei.demo.aop.aspectj.CustomerBo.addCustomer表示拦截CustomerBo中的addCustomer方法,(..)代表参数匹配,此处表示匹配任意数量的参数,可以是0个也可以是多个,如果你确定这个方法不需要使用参数可以直接用(),还可以使用(*)来匹配一个任意类型的参数,还可以使用 (* , String),这样代表匹配两个参数,第二个参数必须是String 类型的参数
5. AspectJ表达式,可以对整个包定义,例如,execution(* com.lei.service..*.*(..))表示切入点是com.lei.sevice包中的任意一个类的任意方法,具体的表达式请自行百度。
第二步,配置Spring配置文件,
配置Spring-AOP-AspectJ.xml文件,如下:

<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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="customerBo" class="com.lei.demo.aop.aspectj.CustomerBo"/> <bean id="logAspect" class="com.lei.demo.aop.aspectj.LoggingAspect" /> </beans>

解释:
1. <aop:aspectj-autoproxy/>启动AspectJ支持,这样Spring会自动寻找用@Aspect注释过的类,其他的配置与spring普通bean配置一样。
测试:
执行App.java如下:

package com.lei.demo.aop.aspectj; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class App {
public static void main(String[] args) { ApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "Spring-AOP-AspectJ.xml" });
ICustomerBo customer=(ICustomerBo)appContext.getBean("customerBo"); customer.addCustomer(); System.out.println("-------------------------------------------"); customer.deleteCustomer(); }
}

结果:
logBefore() is running ...
hijacked:addCustomer
**********
addCustomer() is running ...
-------------------------------------------
deleteCustomer() is running ...
logAfter() is running ...
hijacked:deleteCustomer
**********
二、 将Advice和Pointcut分开
需要三步,
- 创建Pointcut
- 创建Advice
- 配置Spring的配置文件
第一步,PointcutsDefinition.java定义了Pointcut,如下:

package com.lei.demo.aop.aspectj; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; @Aspect
public class PointcutsDefinition { @Pointcut("execution(* com.lei.demo.aop.aspectj.CustomerBo.*(..))")
public void customerLog() {
}
}

解释:
1. 类声明前加入@Aspect注释,以便被框架扫描到。
2. @Pointcut是切入点声明,指定需要注入的代码的位置,如上例中指定切入点为CustomerBo类中的所有方法,在实际业务中往往是指定切入点到一个逻辑层,例如 execution (* com.lei.business.service.*.*(..)),表示aop切入点为service包中所有类的所有方法,具体的表达式后边会有介绍。
3. 方法customerLog是一个签名,在Advice中可以用此签名代替切入点表达式,所以不需要在方法体内编写实际代码,只起到助记功能,例如此处代表操作CustomerBo类时需要的切入点。
第二步,创建Advice类
LoggingAspect.java如下:

package com.lei.demo.aop.aspectj; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; @Aspect
public class LoggingAspect { @Before("com.lei.demo.aop.aspectj.PointcutsDefinition.customerLog()")
public void logBefore(JoinPoint joinPoint){
System.out.println("logBefore() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
} @After("com.lei.demo.aop.aspectj.PointcutsDefinition.customerLog()")
public void logAfter(JoinPoint joinPoint){
System.out.println("logAfter() is running ...");
System.out.println("hijacked:"+joinPoint.getSignature().getName());
System.out.println("**********");
}
}

注释:
1. @Before和@After使用PointcutsDefinition中的方法签名代替Pointcut表达式找到相应的切入点,即通过签名找到PointcutsDefinition中customerLog签名上的Pointcut表达式,表达式指定切入点为CustomerBo类中的所有方法。所以此例中Advice类LoggingAdvice,为CustomerBo中的所有方法都加入了@Before和@After两种类型的两种操作。
2. 对于PointcutsDefinition来说,主要职责是定义Pointcut,可以在其中第一多个切入点,并且可以用便于记忆的方法签名进行定义。
3. 单独定义Pointcut的好处是,一是通过使用有意义的方法名,而不是难读的Pointcut表达式,使代码更加直观;二是Pointcut可以实现共享,被多个Advice直接调用。若有多个Advice调用某个Pointcut,而这个Pointcut的表达式在将来有改变时,只需修改一个地方,维护更加方便。
第三步,配置Spring配置文件,配置文件并没有改变
配置Spring-AOP-AspectJ.xml文件,如下:

<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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="customerBo" class="com.lei.demo.aop.aspectj.CustomerBo"/> <bean id="logAspect" class="com.lei.demo.aop.aspectj.LoggingAspect" /> </beans>

App.java不变,运行测试代码App.java
输出结果:
logBefore() is running ...
hijacked:addCustomer
**********
addCustomer() is running ...
logAfter() is running ...
hijacked:addCustomer
**********
-------------------------------------------
logBefore() is running ...
hijacked:deleteCustomer
**********
deleteCustomer() is running ...
logAfter() is running ...
hijacked:deleteCustomer
**********
Spring AOP AspectJ的更多相关文章
- Spring AOP + AspectJ annotation example
In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...
- Spring AOP + AspectJ Annotation Example---reference
In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...
- 关于 Spring AOP (AspectJ) 该知晓的一切
关联文章: 关于Spring IOC (DI-依赖注入)你需要知道的一切 关于 Spring AOP (AspectJ) 你该知晓的一切 本篇是年后第一篇博文,由于博主用了不少时间在构思这篇博文,加上 ...
- Spring学习(十八)----- Spring AOP+AspectJ注解实例
我们将向你展示如何将AspectJ注解集成到Spring AOP框架.在这个Spring AOP+ AspectJ 示例中,让您轻松实现拦截方法. 常见AspectJ的注解: @Before – 方法 ...
- 关于 Spring AOP (AspectJ) 你该知晓的一切
版权声明:本文为CSDN博主「zejian_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/javazej ...
- 关于 Spring AOP (AspectJ) 你该知晓的一切 (转)
出处:关于 Spring AOP (AspectJ) 你该知晓的一切
- Spring AOP AspectJ Pointcut Expressions With Examples--转
原文地址:http://howtodoinjava.com/spring/spring-aop/writing-spring-aop-aspectj-pointcut-expressions-with ...
- spring AOP AspectJ 定义切面实现拦截
总结记录一下AOP常用的应用场景及使用方式,如有错误,请留言. 1. 讲AOP之前,先来总结web项目的几种拦截方式 A: 过滤器 使用过滤器可以过滤URL请求,以及请求和响应的信息,但是过 ...
- Spring AOP @AspectJ 入门基础
需要的类包: 1.一个简单的例子 Waiter接口: package com.yyq.annotation; public interface Waiter { void greetTo(String ...
随机推荐
- Java并发编程实战(chapter_1)(原子性、可见性)
混混噩噩看了很多多线程的书籍,一直认为自己还不够资格去阅读这本书.有种要高登大堂的感觉,被各种网络上.朋友.同事一顿外加一顿的宣传与传颂,多多少少再自我内心中产生了一种敬畏感.2月28好开始看了之后, ...
- Unix 让进程安全地退出
终止一个进程有很多方法(暂只说linux环境):前台运行的进程,如果没有提供退出功能,我们通常会Ctrl+C进行终止:后台或守护进程,如果也没有提供退出命令啥的,咱通常会kill掉:此外还有类似关机或 ...
- python 中的 args,*args,**kwargs的区别
一.*args的使用方法 *args 用来将参数打包成tuple给函数体调用 例子一:def function(*args): print(args, type(args))function ...
- python函数名称空间
一.命名空间概念 命名空间(name space),若变量x=1,1存放在内存中,命名空间是存放名字x.x与1绑定关系的地方.命名空间分三种: locals:函数内的名称空间,包括局部变量和形参 gl ...
- Java路径类问题总结
一.获取路径: 单独的Java类中获得绝对路径根据java.io.File的Doc文挡,可知: 默认情况下new File("/")代表的目录为:System.getPropert ...
- linux性能调试之iostat
iostat用来监控调试linux系统的IO性能. 一般用法: iostat -xdct time_interval count [disk] -x:显示扩展统计项,如果不使用-x参数只会打印基本统计 ...
- Javascript面向对象编程(三):非构造函数的继承
转载自:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html 一.什 ...
- 大数据 --> 分布式文件系统HDFS的工作原理
分布式文件系统HDFS的工作原理 Hadoop分布式文件系统(HDFS)是一种被设计成适合运行在通用硬件上的分布式文件系统.HDFS是一个高度容错性的系统,适合部署在廉价的机器上.它能提供高吞吐量的数 ...
- 如何打包静态库.a文件 iOS
代码调试好了开始打包成sdk,下面是将要打包的FRSDK代码(FRSDK.h暴露在外面有别人调用) 1.创建新工程(Xcode File-New-Project) 2.把下面的红色框的东西移除 3.将 ...
- git解决修改代码后无法push的问题failed to push some refs to 'ssh://git@xxx.xxx.xx/xx.git'
今天在使用git提交代码的时候,犯了个很低级的错误,按照一切流程当我add并commit提交代码,最后使用push到远程仓库, 接下来奇怪的事情发生了,push之后,查看远程仓库代码并没有发现提交记录 ...