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. C++_函数1-编程的基本模块函数

    以下是<C++ Primer Plus>中第七章的内容: 使用C++函数的3个步骤: 提供函数定义 提供函数原型 调用函数 7.1.1 定义函数 函数分成两类:没有返回值的函数.有返回值的 ...

  2. Codeforces - 38G 可持久化Treap 区间操作

    题意:\(n\)个人排队,每个人有重要度\(p\)和不要脸度\(c\),如果第\(i\)个人的重要度大于第\(i-1\)个人的重要度,那么他们之间可以交换,不要脸度-1,交换后先前的第\(i\)个人也 ...

  3. TransactionScope小例

    1 public static class DataTableHelper { public static List<T> ToModel<T>(this DataTable ...

  4. 从fis中得来的数据结构,Object版,

    /* * config * caoke */ 'use strict'; //You can't use merge in util.js function merge(source, target) ...

  5. PIE SDK打开静止卫星数据

    1. 功能简介 静止卫星是位于地球赤道上空约3.58万km处,与地面始终保持相对静止的卫星,静止卫星的特点是覆盖区域广,具有很强的机动灵活性,能够对特定区域进行分钟级高重复观测,可快速监测灾害目标的动 ...

  6. 千图网爬图片(BeautifulSoup)

    import requests from bs4 import BeautifulSoup import os #导入os模块 class TuKuSpider(): ""&quo ...

  7. Json化数据-调微信接口

    // 先获取用户openid列表 List<String> openids = wxPhotoUpload.getUserOpenIdList(access_token); TreeMap ...

  8. DB Intro - MongoDB User

    MongoDB 3.0 用户创建   摘要: MongoDB 3.0 安全权限访问控制,在添加用户上面3.0版本和之前的版本有很大的区别,这里就说明下3.0的添加用户的方法. 环境.测试: 在安装Mo ...

  9. VIRTIO概述和基本原理

    http://smilejay.com/2012/11/virtio-overview/ (KVM连载)5.1.1 VIRTIO概述和基本原理(KVM半虚拟化驱动) 11/15/2012MASTER  ...

  10. 使用urllib和http.cookiejar获取python老男孩学员成绩

    打开http://crm.oldboyedu.com/crm/grade/single/ 鼠标右键查看源代码,可以看到我们需要post的name.如下: 这里需要在post试提交token和searc ...