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. poj1182 食物链 带权并查集

    题目传送门 题目大意:大家都懂. 思路: 今天给实验室的学弟学妹们讲的带权并查集,本来不想细讲的,但是被学弟学妹们的态度感动了,所以写了一下这个博客,思想在今天白天已经讲过了,所以直接上代码. 首先, ...

  2. HDU - 3652 数位DP 套路题

    题意:统计能被13整除和含有13的数的个数 解法没法好说的..学了前面两道直接啪出来了 PS.HDU深夜日常维护,没法交题,拿网上的代码随便对拍一下,输出一致 #include<bits/std ...

  3. SPOJ - LOCKER 数论 贪心

    题意:求出\(n\)拆分成若干个数使其连乘最大的值 本题是之江学院网络赛的原题,计算规模大一点,看到EMAXX推荐就做了 忘了大一那会是怎么用均值不等式推出结果的(还给老师系列) 结论倒还记得:贪心分 ...

  4. 深入剖析PHP输入流 php://input

    另附一个一个连接: http://www.nowamagic.net/academy/detail/12220520 ///////////////////////////////////////// ...

  5. Redis主从、哨兵、集群的简单区别

    2018-10-26 主从:读写分离,备份哨兵:监控,自动转移,选主集群:数据 hash 分片,同时包含主从及哨兵特性

  6. 金融量化分析-python量化分析系列之---使用python获取股票历史数据和实时分笔数据

    财经数据接口包tushare的使用(一) Tushare是一款开源免费的金融数据接口包,可以用于获取股票的历史数据.年度季度报表数据.实时分笔数据.历史分笔数据,本文对tushare的用法,已经存在的 ...

  7. Java 写入pdf文件

    import java.awt.Color; import java.io.File; import java.io.FileOutputStream; import com.lowagie.text ...

  8. oracle 备份恢复篇(二)---rman 增备恢复--不完全恢复

    一,环境准备 全备脚本: export TMP=/tmp export TMPDIR=$TMP export ORACLE_BASE=/u01 export ORACLE_SID=prod expor ...

  9. linux无敌权限之chattr

    chattr 修改文件或者目录的文件属性,添加超级权限 -R 递归修改文件机子目录 -V 显示详细修改的内容 + 在原有的基础上追加参数 — 减参数 = 跟新为指定参数 a append 设定改参数后 ...

  10. python 爬虫系列02-小说

    本爬虫为网络上的.. # # -*- coding:UTF-8 -*- # from bs4 import BeautifulSoup # import requests # if __name__ ...