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 ...
随机推荐
- 22.jQuery(实例)
1.开关灯效果 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- Problem : 1012 ( u Calculate e )
/*tips:本题只有输入,没有输出,在线测试只检测结果,所以将前面几个结果罗列出来就OK了.为了格式输出问题纠结了半天,最后答案竟然还是错的....所以啊,做题还是得灵活变通.*/ #include ...
- 【Unity与23种设计模式】适配器模式(Adapter)
GoF中定义: "将一个类的接口转换成为客户端期待的类接口.适配器模式让原本接口不兼容的类能一起合作." 适配器模式与装饰模式有一定的相似之处 两者都是在着手解决C#不能多继承的问 ...
- linux操作日志:远程登录设置
想要远程linux服务器,首先需要在服务器上开通ssh服务,安装命令如下: sudo apt-get install openssh-server 在上图的提示中,输入“y”,继续等待安装,安装成 ...
- python笔记之类
类 python不直接支持私有方式,可以在方法或者属性之前加上双下划线,将其变为私有,即外部无法直接调用 访问私有方法或者属性,方法是: _<类名><变量名> 首先类定义 # ...
- 关于MD5+salt盐加密
MD5+salt 最近浏览浏览一些帖子时,发现曾经引以为傲的md5加密算法,虽然是无法解密的算法,但是现在可以通过FELHELP(谷歌浏览器插件)或者一些字典可以套出来,.但是当md5+salt值时, ...
- Vue之七导航守卫
{ path:'/',component:Recommend,beforeEnter: (to, from, next) => { console.log(to); ajax('get','/a ...
- react开发
webpack.config.js var webpack=require("webpack"); var htmlWebpackPlugin=require('html-webp ...
- NEO从入门到开窗(4) - NEO CLI
一.唠叨两句 首先,我们都知道区块链是去中心化的,其中节点都是对等节点,每个节点都几乎有完整的区块链特性,CLI就是NEO的一个命令行对等节点,当然也有GUI这个项目,图形化的NEO节点.节点之间需要 ...
- 【django之权限组件】
一.需求分析 RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,一个角色拥有若干权限.这样,就构造成& ...