上一章 详解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)轻量级集成开发—第5章 剖析Spring3.x AOP特性01
下一章 详解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)轻量级集成开发—第7章 笔者带走进Spring3.x MVC的世界
目录
一、基于Schema风格配置AOP增强处理;
二、基于Schema风格配置全局切入点;
三、Spring AOP与AspectJ AOP的关系;
四、使用@Aspect定义切面;
五、基于Annotation风格配置AOP增强处理;
六、基于Annotation风格配置全局切入点;
前言
笔者在上一章节中,为大家详细且深入的讲解了有关AOP的一些基础知识。那么从本章开始,咱们要开始接着学习有关Spring AOP的后续知识,这些知识包括:增强处理、切入点配置、以及如何使用基于AspectJ的方式配置Spring AOP。但是在学习这些技术之前,笔者还是要提醒各位,掌握基础相对于进阶来说是必经之路,没有一步登天,所以耐下心学习,才能够让你成长的更快。
其次,有些朋友在阅读笔者博文的时候,往往容易误解笔者博文的标题。总是觉得笔者在讲解的时候少了些许后续章节应该包含的东西,在此笔者有必要澄清一些事实。笔者打算对每一章的知识点,逐步分析、逐步讲解,这是需要极其漫长的过程和时间的。所以并不会在某一章节就对所有的知识点进行全方位概括,当然如果是因为博文的标题误导了你,笔者只能对你说声抱歉。
最后还要提及一点的是,由于笔者会经常维护、更新早期博文的内容,所以如果大家有兴趣还是可以再次进行阅读,或许你会有意想不到的收获。
一、详解AOP之增强处理
上一章中,笔者为大家简单的介绍了增强处理的一些概念。还记得什么是增强处理吗?增强处理无非就是定义了通知的执行时机、执行顺序。如果你无法理解什么是执行时机与执行顺序,那么请你回想下咱们在上一章编写JDK动态代理时,是否显式的指定过代理业务的执行?其实增强处理无法就是隐式的帮你做了这些事情而已。在Spring AOP中,增强处理一共包含如下5种类型:
1、前置通知(Before advice):代理业务执行于被拦截的方法之前;
2、后置通知(After advice):代理业务执行于被拦截的方法之后;
3、环绕通知(Around advice):代理业务执行于被拦截的方法之前或之后;
4、异常通知(After throwing advice):代理业务执行于被拦截的方法抛出异常后;
5、返回时通知(After returning advice):代理业务执行于被拦截的方法返回之前;
在基于Schema的AOP中配置中,我们可以通过使用如下标签配置Spring AOP的增强处理:
1、<aop:before/>:用于配置前置通知(Before advice);
2、<aop:after/>:用于配置后置通知(After advice);
3、<aop:around/>:用于配置环绕通知(Around advice);
4、<aop:after-throwing/>:用于配置异常通知(After throwing advice);
5、<aop:after-returning/>:用于配置返回通知(After returning advice);
上述标签我们可以将其称之为增强处理标签,因为这些标签均带有部分相同属性。分别为:method、pointcut、pointcut-ref、throwing和returning。其中属性“method”用于指定作为增强处理类型的切面类的指定方法。属性“pointcut”允许定义一个表达式,该表达式的作用就是拦截指定切入点,并且该表达式支持通配符“*”和“..”。其中通配符“*”代表了任意命名模式的匹配,而“..”则代表了接受0—N个任意类型参数的方法。属性“pointcut-ref”用于引用一个已经存在的切入点名称,换句话来说,该属性可以用于引用一个全局拦截切入点表达式。属性“throwing”仅针对<aop:after-throwing/>标签有效,该属性用于指定一个参数,异常通知(After throwing advice)便可以通过这个参数访问委托对象的指定方法抛出的异常。属性“returning”同样仅针对<aop:after-returning/>标签有效,该属性用于指定一个参数,返回时通知(After returning advice)便可以通过这个参数访问委托对象的指定方法的返回值。
笔者打算先从前置通知(Before advice)和后置通知(After advice)开始讲起,因为这两个通知是Spring AOP增强处理中最为简单,同时也是最容易理解的。前置通知(Before advice)无非就是在切入点执行之前首先执行代理业务,而后置通知(After advice)则反之。
基于Schema的风格配置Before and After增强处理:
<aop:config> <aop:aspect id="logAspect" ref="logBean" order="1"> <!-- 前置通知 --> <aop:before method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" /> <!-- 后置通知 --> <aop:after method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" /> </aop:aspect> </aop:config> <bean name="logBean" class="org.johngao.bean.LogBean" />
在上述配置文件中,笔者为切入点定义了2个通知,分别为前置通知(Before advice)和后置通知(After advice)。在切入点执行之前首先执行前置通知(Before advice),然后再执行切入点,最后执行后置通知(After advice)。其中属性“pointcut”的值为:"execution(* org.johngao.bean.LoginBean.*(..))" 。也就是说指定通知将拦截org.johngao.bean包下LoginBean类型的所有带参或无参方法。当你看到这里的时候,或许你已经明白,在一个切入点内部,允许同时定义多个通知。
Before and After通知实现:
/** * 模拟前置通知、后置通知 * * @author JohnGao * * @param JoinPoint: 连接点 * * @return void */ public void logTest(JoinPoint joinPoint) { /* 获取委托对象指定方法参数 */ Object[] params = joinPoint.getArgs(); for(Object param: params) System.out.println(param); /* 获取委托对象指定方法名称 */ System.out.println(joinPoint.getSignature().getName()); /* 获取委托对象实例 */ joinPoint.getTarget(); /* 获取代理对象实例 */ joinPoint.getThis(); System.out.println("日志记录..."); }
在上述程序示例中,笔者使用到了AspectJ提供的JoinPoint接口。开发人员使用JoinPoint接口可以很方便的访问到委托对象的上下文信息,并且在实际开发过程中,这些上下文信息对于开发人员而言至关重要。JoinPoint接口的常用方法如下:
方法名称 | 方法返回值 | 方法描述 |
getArgs() | Object[] | 获取委托对象的目标方法参数列表,注意:由于返回数组所以需要拆分 |
getSignature() | Signature | 获取委托对象的方法签名 |
getTarget() | Object | 获取委托对象实例 |
getThis() | Object | 获取代理对象实例 |
当然JoinPoint接口还派生有另一个常用的扩展接口,那便是ProceedingJoinPoint接口。该接口仅限用于环绕通知(Around advice),并且相对JoinPoint接口而言,ProceedingJoinPoint接口为开发人员提供有2个新增用于执行委托对象的方法,分别为:
方法名称 | 方法返回值 | 方法描述 |
proceed() | Object | 用于执行委托对象的目标方法 |
proceed(java.lang.Object[] args) | Object | 用于执行委托对象的目标方法,用新参数替换原先入参 |
至于如何使用ProceedingJoinPoint接口,大家目前不必着急,笔者在后续章节自然会进行讲解。为了更加形象的描述不同通知的执行时机与执行顺序,笔者接下来会为大家展示各种通知执行时序图。
Before and After增强处理执行时序图:
当大家理解前置通知(Before advice)和后置通知(After advice)后,笔者接下来将会为大家讲解异常通知(After throwing advice)的配置和使用。所谓异常通知(After throwing advice)无非就是在切入点抛出异常之后执行代理业务,Spring的增强处理为开发人员提供了多种环境下执行通知的机会,在此笔者不得不佩服Rod Johnson丰富的想象力及“创造力”。
基于Schema的风格配置After throwing增强处理:
<aop:config> <aop:aspect id="logAspect" ref="logBean" order="1"> <!-- 异常通知 --> <aop:after-throwing method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" /> </aop:aspect> </aop:config> <bean name="logBean" class="org.johngao.bean.LogBean" />
如果你定义的切入点并没有往外抛出异常,通知是无法执行的。所以使用异常通知(After throwing advice)的时候,我们务必需要将为切入点throws异常。
还记得笔者在上一章节提到过的throwing属性吗?其仅针对<aop:after-throwing/>标签有效,该属性用于指定一个参数,异常通知(After throwing advice)便可以通过这个参数访问委托对象的指定方法抛出的异常。使用throwing属性指定参数:
<aop:after-throwing method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" throwing="exception" />
捕获委托对象的指定方法抛出的异常:
/** * 模拟异常通知 * * @author JohnGao * * @param JoinPoint: 连接点, Exception: 异常信息 * * @return void */ public void logTest(JoinPoint joinPoint, Exception exception) { System.out.println(exception); }
通过上述程序示例我们可以看出,一旦委托对象的目标方法抛出异常后,我们便可以在通知中通过属性“exception”访问所抛出的异常信息。当然定义在通知中的方法参数,Spring的IOC容器自然会负责其初始化工作,所以你无须关心这些“琐事”,尽可能的关注于你的业务既可。
After throwing advice增强处理执行时序图:
返回时通知(After returning advice)其实也比较简单,该通知执行于被拦截的方法返回之前。也就是说当返回时通知(After returning advice)拦截切入点后,应当首先执行切入点,最后切入点即将返回时再执行通知。
基于Schema的风格配置After returning增强处理:
<aop:config> <aop:aspect id="logAspect" ref="logBean" order="2"> <!-- 返回时通知 --> <aop:after-returning method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" /> </aop:aspect> </aop:config> <bean name="logBean" class="org.johngao.bean.LogBean" />
还记得笔者在上一章节提到过的returning属性吗?其仅针对<aop:after-returning/>标签有效,该属性用于指定一个参数,返回时通知(After returning advice)便可以通过这个参数访问委托对象的指定方法的返回值。使用returning属性指定参数:
<aop:after-returning method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" returning="rvt" />
获取委托对象的目标方法返回值:
/** * 模拟返回时通知 * * @author JohnGao * * @param JoinPoint: 连接点, Object: 返回值信息 * * @return void */ public void logTest(JoinPoint joinPoint, Object rvt) { System.out.println(rvt); }
通过上述程序示例我们可以看出,如果需要获取委托对象的目标方法的返回值时,我们可以通过定义<aop:after-returning/>标签中的“returning”属性即可。但这里需要注意的是,returning属性的属性名称务必和通知方法中的属性名称保持一致。
After returning advice增强处理执行时序图:
笔者至此已经为大家讲解了前置(Before advice)、后置(After advice)、异常(After throwing advice)、返回时(After returning advice)等4种通知的配置和使用,那么接下来笔者就开始讲解环绕通知(Around advice)。至于为什么需要将环绕通知(Around advice)放在最后一个讲解?并不是因为它相对其他几个通知更复杂,而是因为这个通知更特殊。
但从字面上的理解,很多开发人员会错误的将环绕通知(Around advice)理解为是前置通知(Before advice)和后置通知(After advice)的结合体。以为该通知无非就是在切入点的执行前后各执行一次,其实这是错误的,笔者希望大家不要因为字面的显浅理解就妄下定论,免得贻笑大方。
环绕通知(Around advice)适用的场景更多的基于并发环境,并且该通知可以满足于切入点之前或者之后执行,甚至可以根据实际业务来判断是否执行。这才是使用环绕通知(Around advice)真正的目的。
基于Schema的风格配置Around增强处理:
<aop:config> <aop:aspect id="logAspect" ref="logBean" order="1"> <!-- 环绕通知 --> <aop:around method="logTest" pointcut="execution(* org.johngao.bean.LoginBean.*(..))" /> </aop:aspect> </aop:config> <bean name="logBean" class="org.johngao.bean.LogBean" />
ProceedingJoinPoint接口派生于JoinPoint接口,该接口仅限于环绕通知(Around advice)获取委托对象的上下文信息使用。笔者刚才也提到过,在实际开发过程中,我们可以使用环绕通知(Around advice)根据实际业务,决定通知是否执行,以及何时执行。
Around通知实现:
/** * 模拟环绕通知 * * @author JohnGao * * @param ProceedingJoinPoint: 连接点 * * @return void */ public void logTest(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("日志记录..."); /* 执行委托对象的目标方法 */ proceedingJoinPoint.proceed(); System.out.println("日志记录..."); }
ProceedingJoinPoint接口的proceed()方法用于执行委托对象的目标方法。然而ProceedingJoinPoint接口还提供有另外一个带参的proceed(java.lang.Object[] args)方法,该方法除了可以用于执行委托对象的目标方法外,还支持使用新参数替换原先入参。
使用proceed(java.lang.Object[] args)方法替换原先入参:
/* 执行委托对象的目标方法 */ proceedingJoinPoint.proceed(new Object[]{"新入参,替换原先入参"});
一旦使用proceed(java.lang.Object[] args)方法替换原先入参后,新参数将会覆盖之前传递给委托对象的目标方法参数。当然如果你不希望替换原先入参,笔者建议你还是使用proceed()方法即可。
相关推荐
在"spring-ssj.rar_spring_spring+Struts2+jpa集成"这个压缩包中,我们很可能会找到一个示例项目,展示了如何将Spring、Struts2和JPA进行集成。以下是这个集成过程的一些关键知识点: 1. **Spring配置**:首先,...
Spring MVC、Spring 和 Spring Data JPA 是 Java 开发中非常重要的三个框架,它们共同构建了一个强大的企业级应用开发环境。Spring MVC 是一个用于构建 Web 应用的模型-视图-控制器(MVC)框架,Spring 提供了依赖...
综上所述,SSJ框架的集成利用了Spring的灵活性和控制反转,Struts2的MVC设计模式,以及JPA的数据持久化能力,为企业级应用提供了强大而灵活的开发基础。在实际项目中,开发者可以根据需求调整和扩展这个框架,以满足...
**Spring+Struts2+JPA 整合详解** 在Java Web开发中,Spring、Struts2和JPA是三个非常重要的框架。Spring作为一个全面的轻量级框架,提供了依赖注入(DI)和面向切面编程(AOP)等功能;Struts2是一个强大的MVC框架...
Struts1.x、Spring 和 JTA(Java Transaction API)是Java Web开发中常见的三大技术,它们各自在应用程序架构中承担着不同的角色。本集成例子旨在展示如何将这三者结合,构建一个完整的业务处理系统。 Struts1.x是...
SSJ,全称为Struts2、Spring和JPA的组合,是Java开发中常见的Web应用程序架构模式。这个项目采用SSH框架,即Struts2作为MVC(Model-View-Controller)框架,Spring作为依赖注入(Dependency Injection,DI)和应用上...
SSH(Spring、Struts、Hibernate)是Java Web开发中经典的三层架构组合,分别负责控制层、业务层和数据访问层。本项目结合了Spring 3.1.0M1、Hibernate 3.X以及Struts2.1.8,旨在提供一个最新的整合示例。 Spring...
在学习jpa时候做的一个struts2+spring+jpa整合的完整例子 包含分页,一个简单的 资产入库系统 并实现了登陆等。
Struts2、Spring和JPA是Java开发中的三大核心框架,它们各自负责应用程序的不同层面,协同工作能够构建出高效、可维护的企业级Web应用。在这个"Struts2.2.3+Spring3.0.5+JPA2.0"的例子中,我们将深入探讨这三个框架...
SSJ.rar_Jap_spring_ssj 是一个与Java应用程序开发相关的压缩包,它结合了Struts、Spring和JAP(可能是Java应用平台)这三种技术。这个项目可能是一个示例或者教程,展示了如何将这三个框架集成在一起以实现特定的...
在Java企业级应用开发中,Spring、Struts和JPA(Java Persistence API)是三个非常重要的框架。它们分别负责不同的职责:Spring作为一个全能型框架,提供了依赖注入(DI)和面向切面编程(AOP),以及对其他框架的...
由于文件的大小限制,所需jar包请自行加入。但要注意在项目发部的时候,tomcat启动时总是报错,解决办法是把Tomcat中项目的lib文件夹下的asm-2.2.3.jar包删掉!或者把Spring的AOP Library包移除就OK了!
Spring 是一个开源的轻量级 Java EE 开发框架,其核心功能包括依赖注入、面向切面编程等。Spring 3.0 版本带来了许多新的特性和改进,如支持 HTTP 方法注解、更强大的 XML 配置等。 - **核心库**: - `spring-core...
SSJ.rar是一个包含示例代码的压缩包,主要展示了如何集成和使用JPI(可能是Java Persistence Interface或自定义的框架)框架与Spring以及Struts2进行Web应用开发。在这个项目中,开发者可能想要演示如何在Spring中...
Spring MVC 框架是Java开发中的一个核心组件,它为构建Web应用程序提供了一种模型-视图-控制器(MVC)架构。Spring框架本身提供了丰富的功能,包括依赖注入、AOP(面向切面编程)、事务管理等,而Spring MVC则是...
Struts1.3、Spring2.5和JPA(基于Hibernate)是Java Web开发中三个重要的框架,它们的集成使用可以构建出强大的企业级应用。这个"Struts1.3+spring2.5+JPA(hibernate) demo"提供了一个实践性的学习案例,帮助初学者...
SSJ通常指的是Struts2、Spring和JPA的集成,这种架构常见于大型企业应用。通过PPTX文件"ssj框架搭建",我们可以了解到如何配置这三个框架,实现它们之间的协作。 6. **示例项目和资源:** - "JPA+-amp+Hibernate+...
苦恼直接使用此包可以进行ssh ssi ssj 使用jpa开发时支持给中ROM,版本:struts2.1.8+spring2.5.6+ibatis2.3+hibernate3.3.2+structjson+dwr不多说了 分两部分,因为每次不超过 15M, 这些包一共 18M多 第二部分 ...
Struts2、Spring2.5 和 JPA 是Java企业级开发中的三大核心技术,它们共同构建了一个强大且灵活的Web应用程序框架。在这个“SSJ使用注释版”项目中,开发者利用注解的方式简化了配置,使得整个应用的搭建更加直观和...
在JavaEE开发中,Spring、SpringMVC和JPA是三个非常重要的框架,它们的整合应用可以极大地提高开发效率和代码质量。这个"Spring SpringMVC Jpa整合Demo"就是一个典型的例子,它展示了如何将这三个框架协同工作,构建...