AOP基于xml配置方式实现

Spring基于xml开发AOP

  •     定义目标类(接口及实现类)
 /**
* 目标类
*/
public interface UserService {
//业务方法
public void getById();
public void add();
public void delete();
public String update();
public void batch();
}
 public class UserServiceImpl implements UserService {
@Override
public void getById() {
System.out.println("UserServiceImpl类的getById方法被调用...");
//抛出异常
System.out.println(1/0);
}
@Override
public void add() {
System.out.println("UserServiceImpl类的add方法被调用...");
}
@Override
public void delete() {
System.out.println("UserServiceImpl类的delete方法被调用...");
// System.out.println(1/0);
}
@Override
public String update() {
System.out.println("UserServiceImpl类的update方法被调用...");
// System.out.println(1/0);
return "update的返回值";
}
@Override
public void batch() {
System.out.println("UserServiceImpl类的batch方法被调用...");
}
}
  •     定义切面类
 /**
* 切面
*/
public class UserAspect {
//前置通知
public void beforeAdvice(JoinPoint jp){
//获取切入点的方法的名称
String name = jp.getSignature().getName();
System.out.println("前置通知切入点的方法的名称:"+name);
System.out.println("前置通知");
} //后置通知
public void afterAdvice(JoinPoint jp){
//获取切入点的方法的名称
String name = jp.getSignature().getName();
System.out.println("后置通知切入点的方法的名称:"+name);
System.out.println("后置通知");
} //返回通知
//可以获取object类型的返回值
//注意:result名称必须和配置文件中的returning的名称保持一致
public void afterReturningAdvice(JoinPoint jp,Object result){
//获取切入点的方法的名称
String name = jp.getSignature().getName();
System.out.println("返回通知切入点的方法的名称:"+name);
//打印返回值
System.out.println(result);
System.out.println("返回通知");
} //异常通知
public void exceptionAdvice(JoinPoint jp,Exception ex){
//获取切入点的方法的名称
String name = jp.getSignature().getName();
System.out.println("异常通知切入点的方法的名称:"+name);
//打印异常信息
System.out.println(ex.getMessage());
System.out.println("异常通知");
} //环绕通知
//必须有一个参数:ProceedingJoinPoint
//有返回值:Object
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知前");
//执行业务逻辑方法
Object result = pjp.proceed();
//获取切入点的方法的名称
String name = pjp.getSignature().getName();
System.out.println("环绕通知切入点的方法的名称:"+name);
System.out.println("环绕通知后");
return result;
}
}
  •     配置spring核心配置文件
<?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-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!-- 把切面和业务对象放到容器中 -->
<bean id="userAspect" class="spring.aop.xml.UserAspect"></bean>
<bean id="userServiceImpl" class="spring.aop.xml.UserServiceImpl"></bean> <!-- 配置aop的实现 -->
<aop:config>
<!--
切入点的配置
expression(切入点表达式):指定切哪个方法
-->
<aop:pointcut expression="execution(* *.add*(..))" id="pointCut01"/>
<aop:pointcut expression="execution(* *.delete*(..))" id="pointCut02"/>
<aop:pointcut expression="execution(* *.update*(..))" id="pointCut03"/>
<aop:pointcut expression="execution(* *.getById*(..))" id="pointCut04"/>
<aop:pointcut expression="execution(* *.batch*(..))" id="pointCut05"/> <!-- 切面的配置 -->
<aop:aspect ref="userAspect">
<!--
前置通知的配置:在pointCut01切入点的位置添加beforeAdvice的通知
-->
<aop:before method="beforeAdvice" pointcut-ref="pointCut01"/> <!--
后置通知的配置:在pointCut02切入点的位置添加afterAdvice的通知
-->
<aop:after method="afterAdvice" pointcut-ref="pointCut02"/> <!--
返回通知的配置:在pointCut03切入点的位置添加afterReturningAdvice的通知
returning:返回值的参数名称
-->
<aop:after-returning method="afterReturningAdvice" pointcut-ref="pointCut03" returning="result"/> <!--
异常通知的配置:在pointCut04切入点的位置添加exceptionAdvice的通知
throwing:抛出异常的名称,必须和通知上的形参名称一致
-->
<aop:after-throwing method="exceptionAdvice" pointcut-ref="pointCut04" throwing="ex"/> <!--
环绕通知的配置:在pointCut05切入点的位置添加aroundAdvice的通知
-->
<aop:around method="aroundAdvice" pointcut-ref="pointCut05"/>
</aop:aspect>
</aop:config>
</beans>
  •     测试
 //使用xml方式配置AOP
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-aop-xml.xml")
public class XmlAopTest {
//注入业务对象
@Autowired
private UserService userService; //测试AOP,对切入点进行增强
@Test
public void test(){
//前置通知的测试
// userService.add(); //后置通知的测试(无论有没有异常都会执行)
// userService.delete(); //返回通知的测试(只有业务方法正常执行时,才会执行的通知)
// userService.update(); //异常通知的测试
// userService.getById(); //环绕通知的测试
userService.batch();
}
}

    

AOP的切入点表达式execution

    表达式的写法:修饰关键词   返回值类型   包名.类名.方法名(..)

修饰关键词:protected ,  public  ,  private ….一般都省略不写

返回值类型:一般返回值类型用 * 号代替,表示任意的返回值都可以

方法名中的两个点:表示所带的参数的个数。

        举例如下:

  任意以public修饰的方法都可以

execution(public * *(..))

  任何以set开头的方法都可以

execution(* set*(..))

  任何在AccountService 这个接口下面的方法都可以

execution(* com.xyz.service.AccountService.*(..))

  任何在com.xyz.service 这个包下面的所有类的所有方法都可以

execution(* com.xyz.service.*.*(..))

  任何在com.xyz.service 这个包以及整个包下面的所有子包的所有类的所有方法都可以

execution(* com.xyz.service..*.*(..))

  ..代表这个包及这个包下面的所有子包

Spring中的5种通知类型及参数

      •   前置通知:在目标方法开始之前进行执行的通知

            参数:JoinPoint

      •   后置通知:在目标方法执行之后,无论是否发生异常,都进行执行的通知

            参数:JoinPoint

      •   返回通知:在目标方法正常结束时,才执行的通知

            参数:JoinPoint,Object

      •   异常通知:在目标方法出现异常时才会进行执行的通知

            参数:JoinPoint,Exception

      •   环绕通知:在目标方法执行之前、 之后都会执行的通知

            参数:ProceedingJoinPoint(必须有)



AOP基于注解方式的实现

xml配置中开启spring注解扫描及开启aop注解的自动代理

    

<?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-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!-- 开启spring的注解驱动 -->
<context:component-scan base-package="spring.aop.annotation"></context:component-scan> <!-- 开启aop的自动代理:使用注解实现AOP,这个必须配置 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

    定义接口及接口实现类

    

 此处省略,同xml配置方式相同

    通过注解的方式定义切面类

 /**
* 切面
*/
@Component
@Aspect
public class UserAspect {
//前置通知
@Before(value = "execution(* *.add*(..))")
public void beforeAdvice(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println("前置通知的切入点的方法名:" + name);
System.out.println("前置通知...");
} //后置通知
@After(value = "execution(* *.delete*(..))")
public void afterAdvice(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println("后置通知的切入点的方法名:" + name);
System.out.println("后置通知...");
} //返回通知
@AfterReturning(value = "execution(* *.update*(..))",returning="result")
public void afterReturningAdvice(JoinPoint jp,Object result){
String name = jp.getSignature().getName();
System.out.println("返回通知的切入点的方法名:" + name);
System.out.println(result);
System.out.println("返回通知...");
} //异常通知
@AfterThrowing(value = "execution(* *.getById*(..))",throwing="ex")
public void exceptionAdvice(JoinPoint jp,Exception ex){
String name = jp.getSignature().getName();
System.out.println("异常通知的切入点的方法名:" + name);
System.out.println(ex.getMessage());
System.out.println("异常通知...");
} //环绕通知
@Around(value = "execution(* *.batch*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知前...");
Object result = pjp.proceed();
String name = pjp.getSignature().getName();
System.out.println("环绕通知的切入点的方法名:" + name);
System.out.println("环绕通知后...");
return result;
}
}

    测试

 /**
* 注解形式的AOP的单元测试类
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-aop-annotation.xml")
public class AnnotationAopTest {
@Autowired
private UserService userService; @Test
public void test(){
//注解:前置通知的测试
// userService.add(); //后置通知的测试
// userService.delete(); //返回通知
// userService.update(); //异常通知
// userService.getById(); //环绕通知
userService.batch();
}
}


AOP的实现的更多相关文章

  1. 基于spring注解AOP的异常处理

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...

  2. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  3. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

  4. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  5. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  6. .Net中的AOP系列之构建一个汽车租赁应用

    返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...

  7. .NET里简易实现AOP

    .NET里简易实现AOP 前言 在MVC的过滤器章节中对于过滤器的使用就是AOP的一个实现了吧,时常在工作学习中遇到AOP对于它的运用可以说是很熟练了,就是没想过如果自己来实现的话是怎么实现的,性子比 ...

  8. 在.Net中实现自己的简易AOP

    RealProxy基本代理类 RealProxy类提供代理的基本功能.这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理.这是我们AOP实现的主要依赖. 新建一 ...

  9. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

  10. 【开源】.Net Aop(静态织入)框架 BSF.Aop

    BSF.Aop .Net 免费开源,静态Aop织入(直接修改IL中间语言)框架,类似PostSharp(收费): 实现前后Aop切面和INotifyPropertyChanged注入方式. 开源地址: ...

随机推荐

  1. python之控制流习题+代码

    # !/usr/bin/python3 # -*- coding: utf-8 -*- # @Time :2018/11/26 15:32 # @Author :yosef # @Email :wur ...

  2. 【算法笔记】B1028 人口普查

    1028 人口普查 (20 分) 某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 2 ...

  3. Oracle SET UNUSED的用法

    SET UNUSED的用法 原理:清楚掉字典信息(撤消存储空间),不可恢复.    可以使用 SET UNUSED选项标记一列或者多列不可用.    使用DROP SET UNUSED选项删除被被标记 ...

  4. poj3176

    一.题意:给定一些数,成三角形排列.从上往下走,每个数只能往它相邻的两个数走,一直走到底端得到一条线路.这条线路上的数的和最大是多少 二.思路:简单的动态规划.dp[i+1][j+1]:=以第i+1行 ...

  5. Tesorflow-自动编码器(AutoEncoder)

    直接附上代码: import numpy as np import sklearn.preprocessing as prep import tensorflow as tf from tensorf ...

  6. mongoDB--万能的$关键字

    之前哥的博客写了增删改查的基本用法,其中$set是关键字用来修改值的,但是不关只有set这一个关键字,下面我们就来说一个万能的$关键字 1.常见的等于 大于 小于 大于等于 小于等于 #等于---&g ...

  7. 【python爬虫】用python编写LOL战绩查询

    介绍一个简单的python爬虫,通过Tkinter创建一个客户端,当输入要查询的LOL用户名称的时候,可以显示出当前用户的所在服务器,当前战力和当前段位. 爬取网页地址:http://lol.duow ...

  8. [實現DDD] 第10章 聚合(1)設計原則

    聚合只是將一些實體(Entity)與值對象(Value Object)聚集起來的對象樹嗎?? 有些途徑可能使我們設計出不正確的聚合模型, 如:可能為了對象組合上的方便而將聚合設計的很大;也可能設計的聚 ...

  9. Mavne 打包时出现程序包找到不的问题

    <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactI ...

  10. 移动端本地 H5 秒开方案探索与实现

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 企业微信移动端项目中有需求要展示数据趋势的可视化图表,经过调研,最终决定以单页面 H5 来完成,对 APP 里的一些使用 H5 实现的功能模 ...