1、基于注解开发AspectJ

(1)AspectJ注解

基于注解开发AspectJ要比基于XML配置开发AspectJ便捷许多,所以在实际开发中推荐使用注解方式。关于注解的相关内容如下:

  • @Aspect:用于定义一个切面,注解在切面类上;
  • @Pointcut:用于定义切入点表达式。在使用时需要定义一个切入点方法,该方法是一个返回值void且方法体为空的普通方法;
  • @Before:用于定义前置通知。在使用时通常为其指定value属性值,该值可以是已有的切入点,也可以直接定义切入点表达式;
  • @AfterReturning:用于定义后置返回通知。在使用时通常为其指定value属性值,该值可以是已有的切入点,也可以直接定义切入点表达式;
  • @Around:用于定义环绕通知。在使用时通常为其指定value属性值,该值可以是已有的切入点,也可以直接定义切入点表达式;
  • @AfterThrowing:用于定义异常通知。在使用时通常为其指定value属性值,该值可以是已有的切入点,也可以直接定义切入点表达式。另外,还有一个throwing属性用于访问目标方法抛出的异常,该属性值于异常通知方法中同名的形参一致;
  • @After:用于定义后置(最终)通知。在使用时通常为其指定value属性值,该值可以是已有的切入点,也可以直接定义切入点表达式;

(2)切入点表达式的定义

在通知中使用value属性定义切入点,通过execution函数,可以定义切入点的方法切入。
语法:execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
例如:

  • 匹配所有类public方法 execution(public **(..))
  • 匹配指定包下所有类方法 execution(* com.imooc.dao.*(..)) 不包含子包
  • 匹配子包 execution(* com.imooc.dao..*(..)) ..*表示包、子孙包下所有类
  • 匹配指定类所有方法 execution(* com.imooc.service.UserService.*(..))
  • 匹配实现特定接口所有类方法 execution(* com.imooc.dao.GenericDAO+.*(..))
  • 匹配所有save开头的方法 execution(* save*(..))

(3)代码实现

添加依赖

<!-- AOP联盟依赖 -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--aspectJ相关依赖-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>

创建StuDao类

public class StuDao {
public void save(){
System.out.println("保存");
}
public String modify(){
System.out.println("修改");
return "modify...";
}
public void delete(){
System.out.println("删除");
}
public void findOne(){
System.out.println("查询单条信息");
int i = 1/0;
}
public void findAll(){
System.out.println("查询所有信息");
}
}

创建切面类

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; @Aspect
public class MyAspectAnno { /**
* 前置通知
* @param joinPoint 用于获取切点信息
*/
@Before(value = "execution(* com.aspectj.demo.StuDao.save(..))")
public void before(JoinPoint joinPoint){
System.out.println("前置通知============="+joinPoint);
} /**
* 后置返回通知,通过returning属性可以定义方法返回值,作为参数
* @param result 和returning属性的值保持一致
*/
@AfterReturning(value = "execution(* com.aspectj.demo.StuDao.modify(..))",returning = "result")
public void afterReturing(Object result){
System.out.println("后置返回通知=========="+result);
} /**
* 环绕通知
* 如果不调用ProceedingJoinPoint的proceed方法,那么目标方法就被拦截了
* @param joinPoint 可以调用拦截目标方法执行
* @return 目标代理方法执行返回值
* @throws Throwable
*/
@Around(value = "execution(* com.aspectj.demo.StuDao.delete(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前置通知*************");
Object obj = joinPoint.proceed();
System.out.println("环绕后置通知*************");
return obj;
} //异常通知
@AfterThrowing(value = "execution(* com.aspectj.demo.StuDao.findOne(..))",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知================"+e);
} //最终通知,无论是否出现异常,最终通知总是会被执行的
@After(value = "execution(* com.aspectj.demo.StuDao.findAll(..))")
public void after(){
System.out.println("最终通知==================");
} }

配置applicationContext.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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启AspectJ的注解开发,自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="stuDao" class="com.aspectj.demo.StuDao"></bean>
<bean class="com.aspectj.demo.MyAspectAnno"></bean> </beans>

创建测试类

@Test
public void demo(){ ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
StuDao stuDao = (StuDao) app.getBean("stuDao");
stuDao.save();
stuDao.modify();
stuDao.delete();
stuDao.findAll();
stuDao.findOne();
}

运行结果

(4)切点命名

在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点,可以使用@Pointcut进行定义。
切点方法:private void 无参数方法,方法名为切点名,当通知多个切点时,可以使用||进行连接。
把切面类代码修改为:

@Aspect
public class MyAspectAnno { //前置通知
@Before(value = "myPointcut1()")
public void before(JoinPoint joinPoint){
System.out.println("前置通知============="+joinPoint);
} //后置通知
@AfterReturning(value = "myPointcut2()",returning = "result")
public void afterReturing(Object result){
System.out.println("后置返回通知=========="+result);
} //环绕通知
@Around(value = "myPointcut3()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前置通知*************");
Object obj = joinPoint.proceed();
System.out.println("环绕后置通知*************");
return obj;
} //异常通知
@AfterThrowing(value = "myPointcut4()",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知================"+e);
} //最终通知
@After(value = "myPointcut5()")
public void after(){
System.out.println("最终通知==================");
} @Pointcut(value = "execution(* com.aspectj.demo.StuDao.save(..))")
private void myPointcut1(){} @Pointcut(value = "execution(* com.aspectj.demo.StuDao.modify(..))")
private void myPointcut2(){} @Pointcut(value = "execution(* com.aspectj.demo.StuDao.delete(..))")
private void myPointcut3(){} @Pointcut(value = "execution(* com.aspectj.demo.StuDao.findOne(..))")
private void myPointcut4(){} @Pointcut(value = "execution(* com.aspectj.demo.StuDao.findAll(..))")
private void myPointcut5(){} }

2、基于XML配置开发AspectJ

添加依赖

<!-- AOP联盟依赖 -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--aspectJ相关依赖-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>

创建StuDao接口和实现类StuDaoImpl
StuDao接口

public interface StuDao {
public void save();
public void delete();
public String modify();
public void findOne();
public void findAll();
}

StuDaoImpl实现类

public class StuDaoImpl implements StuDao {
@Override
public void save() {
System.out.println("保存");
} @Override
public String modify() {
System.out.println("修改");
return "modify...";
} @Override
public void delete() {
System.out.println("删除");
} @Override
public void findOne() {
System.out.println("查询单条记录");
int i = 1/0;
} @Override
public void findAll() {
System.out.println("查询所有记录");
}
}

创建切面类

public class MyAspectjXml {

    //前置通知
public void before(){
System.out.println("前置通知===============");
} //后置返回通知
public void afterReturing(Object result){
System.out.println("后置返回通知============="+result);
} //环绕通知
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前置通知**************");
Object obj = joinPoint.proceed();
System.out.println("环绕后置通知**************");
return obj;
} //异常通知
public void afterThrowing(Throwable e){
System.out.println("异常通知=================="+e);
} //最终通知
public void after(){
System.out.println("最终通知===================");
}
}

配置applicationContext.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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--配置目标类-->
<bean id="stuDao" class="com.aspectj.demo2.StuDaoImpl"></bean>
<!--配置切面类-->
<bean id="myAspectjXml" class="com.aspectj.demo2.MyAspectjXml"></bean>
<!--AOP相关配置-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pointcut1" expression="execution(* com.aspectj.demo2.StuDao.save(..))"></aop:pointcut>
<aop:pointcut id="pointcut2" expression="execution(* com.aspectj.demo2.StuDao.modify(..))"></aop:pointcut>
<aop:pointcut id="pointcut3" expression="execution(* com.aspectj.demo2.StuDao.delete(..))"></aop:pointcut>
<aop:pointcut id="pointcut4" expression="execution(* com.aspectj.demo2.StuDao.findOne(..))"></aop:pointcut>
<aop:pointcut id="pointcut5" expression="execution(* com.aspectj.demo2.StuDao.findAll(..))"></aop:pointcut> <!--配置AOP的切面-->
<aop:aspect ref="myAspectjXml">
<!--配置前置通知-->
<aop:before method="before" pointcut-ref="pointcut1"></aop:before>
<!--配置后置返回通知-->
<aop:after-returning method="afterReturing" pointcut-ref="pointcut2" returning="result"></aop:after-returning>
<!--配置环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3"></aop:around>
<!--配置异常通知-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"></aop:after-throwing>
<!--配置最终通知-->
<aop:after method="after" pointcut-ref="pointcut5"></aop:after>
</aop:aspect>
</aop:config> </beans>

创建测试类

@Test
public void demo(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
StuDao stuDao = (StuDao) app.getBean("stuDao");
stuDao.save();
stuDao.delete();
stuDao.modify();
stuDao.findAll();
stuDao.findOne();
}

运行结果

Spring框架学习09——基于AspectJ的AOP开发的更多相关文章

  1. Spring 基于 AspectJ 的 AOP 开发

    Spring 基于 AspectJ 的 AOP 开发 在 Spring 的 aop 代理方式中, AspectJ 才是主流. 1. AspectJ 简介 AspectJ 是一个基于 java 语言的 ...

  2. Spring框架学习之注解配置与AOP思想

         上篇我们介绍了Spring中有关高级依赖关系配置的内容,也可以调用任意方法的返回值作为属性注入的值,它解决了Spring配置文件的动态性不足的缺点.而本篇,我们将介绍Spring的又一大核心 ...

  3. Spring框架学习07——基于传统代理类的AOP实现

    在Spring中默认使用JDK动态代理实现AOP编程,使用org.springframework.aop.framework.ProxyFactoryBean创建代理是Spring AOP 实现的最基 ...

  4. [ SSH框架 ] Spring框架学习之二(Bean的管理和AOP思想)

    一.Spring的Bean管理(注解方式) 1.1 什么是注解 要使用注解方式实现Spring的Bean管理,首先要明白什么是注解.通俗地讲,注解就是代码里的特殊标记,使用注解可以完成相应功能. 注解 ...

  5. 十四 Spring的AOP的基于AspectJ的注解开发

    Spring的AOP的基于AspectJ的注解开发 创建项目,引入jar包 编写目标类.切面类 配置目标类.切面类 在注解文件里开启AOP的开发 <?xml version="1.0& ...

  6. Spring框架学习——AOP的开发

    一.AOP开发中的相关术语. ——JoinPoint(连接点):指那些可以被拦截到的点.比如增删改查方法都可以增强,这些方法就可以被称为是连接点. ——PointCut:切入点,真正被拦截的点,指对哪 ...

  7. Spring框架学习1

    AnonymouL 兴之所至,心之所安;尽其在我,顺其自然 新随笔 管理   Spring框架学习(一)   阅读目录 一. spring概述 核心容器: Spring 上下文: Spring AOP ...

  8. Spring框架学习(一)

    一. spring概述 Spring 框架是一个分层架构,由 7 个定义良好的模块组成.Spring 模块构建在核心容器之上,核心容器定义了创建.配置和管理 bean 的方式,如图 1 所示. 图 1 ...

  9. 利用基于@AspectJ的AOP实现权限控制

    一. AOP与@AspectJ AOP 是 Aspect Oriented Programming 的缩写,意思是面向方面的编程.我们在系统开发中可以提取出很多共性的东西作为一个 Aspect,可以理 ...

随机推荐

  1. break case

    #include<stdio.h> main() { ; switch (g){ : : printf("haha"); break; : printf("h ...

  2. mysql 原理 ~ innodb恢复机制

    举例说明 机制 数据页A的lsn为100,数据页B的lsn为200,checkpoint lsn为150,系统lsn为300,表示当前系统已经更新到300,小于150的数据页已经被刷到磁盘上,因此数据 ...

  3. CentOS中安装Nginx

    一.背景 最近在写一些自己的项目,用到了nginx,所以自己动手来在Centos7上安装nginx,以下是安装步骤. 二.基本概念以及应用场景 1.什么是nginx Nginx是一款使用C语言开发的高 ...

  4. Docker相关

    1.理念 通过对应用组件的封装.分发.部署.运行等生命周期的管理,使用户的App(可以是一个Web应用或数据库应用等)及其运行环境能够做到“一次封装,处处运行”. 2.一句话总结 解决运行环境和配置问 ...

  5. 【转】linux的特殊符号与正则表达式

    [转]linux的特殊符号与正则表达式 第1章 linux的特殊符号 1.1 通配符 * {} 1.1.1 含义 方便查找文件 通配符是用来找文件名字的. 1.1.2  * 通过find 命令找以 . ...

  6. ARMV8 datasheet学习笔记5:异常模型

    1.前言 2.异常类型描述 见 ARMV8 datasheet学习笔记4:AArch64系统级体系结构之编程模型(1)-EL/ET/ST 一文 3. 异常处理路由对比 AArch32.AArch64架 ...

  7. GetStockObject 理解

    原文地址:https://www.cnblogs.com/Clingingboy/archive/2013/04/13/3017952.html GetStockObject在图形编程中是常用API之 ...

  8. Maven编译时,出现找不到符号

    解决办法: 如果使用的是聚合工程 1.执行project--clean(eclipse)或者build project(intellij),将项目清理一下. 2.执行聚合工程中的  Maven--cl ...

  9. OneNET麒麟座应用开发之三:获取温湿度数据

    对于大气环境监测来说温湿度也是重要的指标.原本计划使用SHT15来采集温湿度数据,不过在OneNET麒麟开发板上,我们发现已经集成有SHT20温湿度传感器,于是我们就使用它了.如下图的红框处: 我们还 ...

  10. 一个简单 JDK 动态代理的实例

    动态代理的步骤: 创建一个实现了 InvocationHandler 接口的类,必须重写接口里的 invoke()方法. 创建被代理的类和接口 通过 Proxy 的静态方法 newProxyInsat ...