1、业务需求: 因为最近在研究审批流的实现,所以在每次save或update的时候,就要走审批流的处理,在每个service中加入审批流的处理方法,显然不大合适,所以由此想到用AOP切面技术来实现。
2、本文环境是struts2 + spring 2.5
3、就像其它的流行技术一样,有注解和XML两种实现方式,aop的实现,也可以通过这两种方式实现,本文用XML的方式开发。
4、先来看看AOP的XML配置:
<!-- 配置日志切面 -->
<bean id="diaryAspect" class="com.testPro.aop.DiaryAspect"></bean>
<aop:config>
<!-- 声明一个切面 -->
<aop:aspect id="myDiaryAspect" ref="diaryAspect">
<aop:pointcut id="Operation"
expression="(execution(* com.testPro.*.service.*.save*(..))) or (execution(* com.weboa.*.service.*.update*(..)))" />
<aop:before pointcut-ref="Operation" method="beforeMethod" />
<aop:after pointcut-ref="Operation" method="afterMethod" />
<aop:after-returning pointcut-ref="Operation" returning="result" method="afterReturning" />
<aop:after-throwing pointcut-ref="Operation" method="throwException" />
</aop:aspect>
</aop:config>
解释:
4.1 首先是方法切点函数:
expression,可用通配符进行方法的配置,语法如下:
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
这么说很抽象,举几个实例:
a、execution(* com.baobaotao.*(..)):匹配com.baobaotao包下所有类的所有方法;
b、execution(* com..*.*DAO.find*(..)):匹配包名前缀为com的任何包下类名后缀为Dao的方法,方法名必须以find为前缀。
关于切点函数的通配,网上有很多总结,这里不再举例。
补充:切点函数支持复合运算符,如我上面的XML配置,就是匹配所有以save或update开头的方法名。
4.2
Aspectj中的增强类型:基本类型有6个。
类型 | 解释 | 成员 |
Before | 增置增强 | value,argNames |
AfterReturning | 后置增强 | value,pointcut,returning,artNames |
Around | 环绕增强 | value,argName |
AfterThrowing | 抛出增强 | value,pointcut,throwing,argNames |
After | Final增强,不管是抛出异常或者是正常退出,该增强都会执行 | value,argName |
DeclareParents | 引介增强 | value,defaultImpl |
4.3 我上面的XML中定义了before,after,afterreturning和afterthrowing的增强(当然直接在切面的实现类里用ANNOTATION配置也是可以的。)
即标签:<aop:before/><aop:after/><aop:after-returning/><aop:after-throwing />
其中属性pointcut-ref是指定义的切面bean的ID,method是指具体定义的切面实体类中的方法。标签中<aop:after-returning/>的returning是指方法返回值。具体和实现类中的参数对应。
5、Aspect实现类(核心)
package com.testPro.aop;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import org.aspectj.lang.JoinPoint;
import com.opensymphony.xwork2.ActionContext;
/**
* 日志切面类
*/
public class DiaryAspect {
// 方法调用前执行
public void beforeMethod(JoinPoint point) {
Object[] args = point.getArgs();
for(Object arg : args){
System.out.println("当前连接点方法运行时的入参列表:" + arg);
}
System.out.println("当前执行方法:"+ point.getSignature().getName());
System.out.println("获取连接点所在的目标对象:"+ point.getTarget().getClass().getName());
System.out.println("获取代理本身:" + point.getThis().getClass().getName());
}
// 方法调用结束后执行
public void afterMethod(JoinPoint point) {
System.out.println("final增强");
}
public void afterReturning(JoinPoint point,int result){
//得到方法名
String className = point.getTarget().getClass().getName();
//得到SESSION
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
HttpSession session = request.getSession();
int userid = Integer.parseInt(session.getAttribute("userid").toString());
System.out.println("后置增强类:目标对象方法返回值:"
+ result);
}
// 抛出异常后执行
public void throwException(JoinPoint point) {
System.out.println("抛出异常后执行" );
}
}
解释:
5.1 因为我实现的是审批流的切面,所以重点业务都放在了后置增强类中。我一开始的时候是放在after中来实现的,后来因为需要用到目标对象方法的返回值,所以就重点写了afterreturning方法。
5.2
关于AOP中的session,因为我用的是STRUTS2的框架,所以用上下文ActionContext直接得到了session。
5.3
连接点信息类:JoinPoint。它包含了很多的信息,包括能得到连接点方法运行时的入参列表,方法签名对象,连接点所在的目标对象,代理对象本身等。
java.lang.Object[] getArgs() | 获取连接点方法运行时的入参列表 |
Signature getSignature() | 获取连接点的方法签名对象 |
java.lang.Object getTarget() | 获取连接点所在的目标对象 |
java.lang.Object getThis() | 获取代理对象本身 |
关于以上四点,我在类TestImpl的saveTest方法中测试,在beforeMethod方法中输出:
当前连接点方法运行时的入参列表:19
当前连接点方法运行时的入参列表:1
当前执行方法:save
获取连接点所在的目标对象:com.testPro.temp.service.impl.TestImpl
获取代理本身:com.testPro.temp.service.impl.TestImpl$$EnhancerByCGLIB$$c7579c95
-----------------------------------------------
【值得注意的地方】
我在类TestImpl的saveTest方法中实现对POJO类Test的insert操作,然后本来的想法是在切面中获取saveTest相当参数,进行反射后,在具体的审批流中对Test实体类进行再次的查询和修改。
但这一思路并没有成功。 主要原因是在service层的save方法中save的Test实体类,在做切面的时候,并没有实际的插入到数据库中,所以我在用select语句去数据库查找时,得不到该信息。主要也是因为事务没有在service的save方法后进行提交,在切面中再生成一个,而是用了同一个事务。即:REQUIRED(如果有事务,那么加入事务,没有的话新创建一个)。
后来觉得切面中也没必要再对save中的实体进行再操作,所以将实体类的操作统一放到service中实现,切面中专心对审批流进行操作。这样的流程就走通了。
-----------------------------------------------
【参考】
http://blog.csdn.net/sin90lzc/article/details/7486145
http://aopalliance.sourceforge.net
《Spring 3.x企业应用开发实战》第七章 基于@AspectJ和Schema的AOP
分享到:
相关推荐
面向切面编程(AOP,Aspect Oriented Programming)是Spring框架中的一个重要特性,它提供了一种模块化和声明式的方式来处理程序中的横切关注点,如日志、事务管理、安全控制等。AOP的核心概念包括切面、通知、连接...
面向切面编程(AOP)是一种编程范式,它旨在减少代码中的重复部分,特别是那些与核心业务逻辑无关但又必须处理的交叉关注点,如日志、事务管理、安全控制等。Spring框架是Java领域中实现AOP的常用工具,它通过提供...
面向切面编程(Aspect-Oriented Programming,AOP)是Spring框架的核心特性之一,它提供了一种优雅的方式来处理系统的横切关注点,如日志、事务管理、性能监控和权限控制等。在Spring中,AOP主要通过代理模式实现,...
面向切面编程(AOP,Aspect Oriented Programming)是Spring框架的重要组成部分,它提供了一种在不修改原有业务代码的基础上,插入额外功能的编程模型。Spring AOP使得开发者能够更方便地实现如日志记录、事务管理、...
在Spring框架中,面向切面编程(AOP)是一种强大的设计模式,它允许开发者将关注点分离,将横切关注点(如日志、事务管理、权限检查等)与核心业务逻辑解耦。本篇文章将深入探讨如何使用Spring的动态代理机制实现AOP...
学习Spring开发的AOP面向切面编程时所需要的jar包,包括com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它扩展了传统的面向对象编程,使得开发者可以方便地实现横切关注点,如日志、事务管理、性能监控等。在Spring中,AOP通过代理...
### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)逐渐暴露出难以应对某些横切关注点(cross-cutting concerns)的问题。为了解决这一挑战,面向方面编程...
面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。 除了类(classes)以外,AOP提供了 切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。
Spring 面向切面编程AOP实现详解 面向切面编程(AOP)是一种编程技术,旨在将横切关注点从业务逻辑中分离出来,提高系统的可扩展性和可维护性。Spring 作为一个流行的 Java 框架,提供了完备的 AOP 实现机制。 1. ...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许我们在不修改源代码的情况下对应用程序的行为进行统一管理和控制。在本实例中,我们将深入探讨如何使用AspectJ技术和XML配置来实现AOP。 首先,了解...
在IT行业中,Spring框架是Java企业级应用开发的首选,其强大的功能之一就是AOP(面向切面编程)。本文将详细解析Spring AOP的三种实现方式,帮助你深入理解这一重要概念。 首先,理解AOP的基本概念至关重要。AOP是...
JAVA Spring AOP面向切面编程笔记
### AOP面向切面编程详解 #### 一、AOP概览 AOP(Aspect-Oriented Programming,面向切面编程)是一种编程思想和技术,它作为OOP(面向对象编程)的一种补充,主要解决了OOP在处理横切关注点方面的不足。在传统的...
### 面向切面编程(AOP) 面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在提高模块化程度,通过将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,使得代码更加清晰、...
面向切面编程(AOP,Aspect Oriented Programming)是一种编程范式,旨在将系统中的关注点分离,使得代码更加模块化,易于维护和扩展。在传统的面向对象编程(OOP)中,业务逻辑往往与日志、事务管理、权限控制等横...
Spring4AOP 面向切面编程实例之方法拦截实例 一下利用Spring4的最后一个版本Spring4.3.9,实现简单的方法拦截实例。 Eclipse 建立java工程,导入必要的jar包,工程目录如下:
2、面向切面编程AOP 在实现过程中,我尽量贴近实际开发与场景,麻雀虽小,五脏俱全,个人感觉这个项目是web框架搭建的一个极简之道实践。 项目中可能还存在很多的问题,希望大家不吝赐教,谢谢。
在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从业务逻辑中分离出来,比如日志记录、事务管理、权限检查等。`@Aspect`是Spring AOP的核心注解,用于定义一个切面。下面我们将详细...
在Spring框架中,动态代理和AOP(面向切面编程)是两个重要的概念,它们极大地增强了代码的可维护性和灵活性。下面将详细讲解这两个概念及其实际应用。 动态代理,是Spring提供的一种机制,允许我们在不修改原对象...