基于注解的Spring AOP的配置和使用
Spring的AOP配置

Spring的AOP配置(2011-04-01 20:38:58)转载标签:分类:SSH框架springaop配置获取参数it1.先写一个普通类:package com.spring.aop;public class Common {public void execute(String username,String password){ System.out.println("------------------普通类----------------");}}2.写一个切面类,用于合法性校验和日志添加:package com.spring.aop;public class Check {public void checkValidity(){System.out.println("------------------验证合法性----------------"); }public void addLog(JoinPoint j){System.out.println("------------------添加日志----------------");Object obj[] = j.getArgs();for(Object o :obj){System.out.println(o);}System.out.println("========checkSecurity=="+j.getSignature().getName());//这个是获得方法名}}3.配置AOP,使用XML方式:(注意红色标志的内容)<?xml version="1.0" encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="common" class="mon"/><bean id="check" class="com.spring.aop.Check"/><aop:config><aop:aspect id="myAop" ref="check"><aop:pointcut id="target" expression="execution(*mon.execute(..))"/><aop:before method="checkValidity" pointcut-ref="target"/><aop:after method="addLog" pointcut-ref="target"/></aop:aspect></aop:config>注意:execution(* com.spring.aop.*.*(..))"/这样写应该就可以了这是com.aptech.jb.epet.dao.hibimpl 包下所有的类的所有方法。
基于SpringBootAOP与自定义注解转义字典值

基于SpringBootAOP与自定义注解转义字典值要基于SpringBoot、AOP和自定义注解来转义字典值,可以按照以下步骤进行:1.创建一个字典表,存储字典值和对应的转义值。
例如,可以创建一个数据库表或者在配置文件中定义一个字典映射关系。
4.在切面方法中,获取需要转义的字段的值,然后根据字典表中的映射关系,找到对应的转义值,并将转义值设置回字段。
5.在需要使用转义值的地方,直接使用被转义后的字段值即可。
下面是一个简单的示例代码:1.创建字典表,例如在配置文件中定义:```yamldict.mapping:gender:0:男1:女``````javaString value( default "";```3.创建AOP切面类:```javapublic class DictTransAspectprivate DictMapping dictMapping;public Object dictTrans(ProceedingJoinPoint joinPoint) throws ThrowableObject result = joinPoint.proceed(;//获取被标记的字段或方法Field field =ReflectionUtils.findField(joinPoint.getTarget(.getClass(, ((MethodSignature) joinPoint.getSignature().getName();DictTrans dictTrans = field.getAnnotation(DictTrans.class);if (dictTrans != null)//获取字段值Object value = field.get(joinPoint.getTarget();//获取字段的字典映射关系Map<String, String> mapping =dictMapping.getMapping(dictTrans.value();//根据字典映射关系转义字段值String transValue = mapping.get(value.toString();//设置转义值回字段field.set(joinPoint.getTarget(, transValue);}return result;}``````javapublic class Userprivate Integer gender;// getter and setter```5.在业务中使用转义后的字段值:```javapublic class UserService// 注入 UserMapper 或者其他数据访问层public User getUserById(String id)User user = userMapper.findById(id);System.out.println(user.getGender(); // 输出转义后的值,例如输出 "男"return user;}```这样,就实现了基于 SpringBoot、AOP 和自定义注解来转义字典值的功能。
【SpringFramework】Spring入门教程(三)使用注解配置

【SpringFramework】Spring⼊门教程(三)使⽤注解配置本⽂主要介绍四个⽅⾯:(1) 注解版本IOC和DI(2) Spring纯注解(3) Spring测试(4) SpringJDBC - Spring对数据库的操作使⽤注解配置Spring⼊门说在前⾯学习基于注解的IoC配置,⼤家脑海⾥⾸先得有⼀个认知,即注解配置和xml配置要实现的功能都是⼀样的,都是要降低模块间的耦合度。
仅仅只是配置的形式不⼀样。
关于实际的开发中到底使⽤xml还是注解,每家公司有着不同的使⽤习惯。
所以这两种配置⽅式我们都需要掌握。
基于注解配置的⽅式也已经逐渐代替xml配置。
所以我们必须要掌握使⽤注解的⽅式配置Spring。
配置步骤注意:如果使⽤Eclipse需要先安装了STS插件,或者使⽤STS开发⼯具创建项⽬。
本⽂使⽤IDEA进⾏演⽰。
1.2.1. 第⼀步:拷贝必备jar包到⼯程的lib⽬录。
注意:在基于注解的配置中,我们还要多拷贝⼀个aop的jar包。
如下图:1.2.2. 第⼆步:在类的根路径下创建⼀个任意名称的xml⽂件(不能是中⽂)注意:基于注解整合时,Spring配置⽂件导⼊约束时需要多导⼊⼀个context命名空间下的约束。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd"></beans>1.2.3. 第⼆步:创建⼀个服务类创建⼀个测试的服务类,并且加⼊使⽤@Component注解,声明该类允许注⼊到Spring容器package org.cjw.service;import ponent;/*使⽤注解配置时,需要将Spring框架启动就创建对象的类表⽰为组件类表⽰组件类使⽤@Component注解*/@Componentpublic class CustomerService {public void save() {System.out.println("-保存数据-");}}1.2.4. 第四步在spring的配置⽂件加⼊扫描注解<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context.xsd"><!-- 声明扫描包及其⼦包的类,如果发现有组件注解的类,就创建对象并加⼊到容器中去 --><context:component-scan base-package="org.cjw" /></beans>1.2.5. 第五步:测试调⽤代码package org.cjw.test;import org.cjw.service.CustomerService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class CustomerServiceTest {@Testpublic void testSave() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");CustomerService customerService = context.getBean(CustomerService.class);customerService.save();}}--测试结果,如果可以调⽤服务⽅法,测试成功。
SpringAOP的原理和应用场景

SpringAOP的原理和应用场景SpringAOP(Aspect-Oriented Programming)是Spring框架中的一个重要组成部分,它提供了一种通过预定义的方式,将横切关注点(Cross-cutting Concerns)与业务逻辑进行解耦的机制。
本文将介绍SpringAOP的原理及其在实际应用场景中的应用。
一、SpringAOP的原理SpringAOP基于代理模式(Proxy Pattern)实现。
在SpringAOP中,通过生成与原始类(被代理类)具有相同接口的代理类,将横切逻辑编织到业务逻辑中。
在运行时,当调用代理类的方法时,会在方法执行前、后或异常抛出时插入相应的横切逻辑代码。
具体而言,SpringAOP使用了以下几个核心概念:1. 切面(Aspect):切面是横切逻辑的模块化单元,它包含了一组通知(Advice)和切点(Pointcut)。
2. 通知(Advice):通知定义了实际的横切逻辑代码,并规定了何时执行该代码。
SpringAOP提供了五种类型的通知:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。
3. 切点(Pointcut):切点指定了在哪些连接点(Join Point)上执行通知。
连接点可以是方法调用、属性访问等程序执行的点。
4. 连接点(Join Point):连接点是程序执行过程中的一个特定点,如方法调用前、方法调用后等。
通知通过切点来选择连接点。
5. 织入(Weaving):织入是将切面应用到目标对象,并创建代理对象的过程。
织入可以在编译时、类加载时或运行时进行。
二、SpringAOP的应用场景SpringAOP可应用于各种场景,用于解决跨越多个模块或类的横切关注点问题。
以下是一些常见的SpringAOP应用场景:1. 日志记录:通过在关键方法的前后插入日志代码,实现对系统运行状态的监控和记录。
aop的原理应用

AOP的原理应用1. 什么是AOPAOP(Aspect-Oriented Programming)是面向切面编程的缩写,它是一种能够通过解耦的方式将横切性关注点模块化的编程范式。
传统的面向对象编程(OOP)主要是通过类和对象来划分和组织代码,但当系统变得复杂时,代码中常常散布着一些与主要业务逻辑无关的、可复用的逻辑(比如日志记录、安全控制、事务管理等),这就导致了代码的重复和耦合度的增加。
而AOP可以通过将这些横切逻辑(称为切面)与主要业务逻辑分离,从而提高代码的可维护性、可测试性和可复用性。
2. AOP的原理AOP的核心原理是在编译期、加载期或运行期利用动态代理技术来实现切面的织入。
具体来说,AOP框架会在目标对象的方法调用前后或者异常抛出时,插入横切逻辑(切面),从而实现对目标对象的增强。
其中,横切逻辑通过切面由切点和增强组成。
•切点:定义了在何处插入切面的准则,比如可以根据类名、方法名或注解等进行精确定位。
•增强:指的是横切逻辑的实现,比如可以在方法调用前后执行某些操作。
织入过程可以通过前置织入、后置织入等方式来实现。
3. AOP的应用场景AOP的特点使得它在很多场景下都能够发挥作用,以下列举了几个常见的应用场景:•日志记录:AOP可以很方便地将日志记录逻辑与主要业务逻辑分离,从而使得代码更加清晰、易于维护。
例如,可以利用AOP在方法调用前后记录方法的输入参数和返回结果。
•安全控制:通过AOP可以在方法调用前进行身份验证、权限检查等安全控制逻辑,从而确保系统的安全性。
•事务管理:AOP可以在方法调用前后添加事务管理逻辑,保证数据的一致性和完整性。
例如,可以在方法调用前开启事务,在方法调用后提交或回滚事务。
•性能监控:利用AOP可以在方法调用前后统计方法的执行时间、请求次数等,通过监控这些性能指标可以优化系统的性能。
•异常处理:AOP可以在方法抛出异常时进行异常处理逻辑,并且可以根据异常类型进行不同的处理。
SpringAOP示例与实现原理总结——传统springaop、基于切面注入、基于@Asp。。。

SpringAOP⽰例与实现原理总结——传统springaop、基于切⾯注⼊、基于@Asp。
⼀、代码实践1)经典的Spring Aop经典的spring aop,是基于动态代理技术的。
实现⽅式上,最常⽤的是实现MethodInterceptor接⼝来提供环绕通知,创建若⼲代理,然后使⽤ProxyBeanFactory配置⼯⼚bean,⽣成拦截器链,完成拦截。
⽰例如下:1package demo.spring;23import org.aopalliance.intercept.MethodInterceptor;4import org.aopalliance.intercept.MethodInvocation;5import org.junit.Test;6import org.junit.runner.RunWith;7import org.springframework.beans.factory.annotation.Autowired;8import org.springframework.test.context.ContextConfiguration;9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;1011 @RunWith(SpringJUnit4ClassRunner.class)12 @ContextConfiguration("classpath:spring-config.xml")13public class TraditionalSpringAopDemo {14 @Autowired15private Service proxy;1617 @Test18public void test() {19 proxy.execute("hello world!");20 }21 }2223interface Service {24void execute(String str);25 }2627class ServiceImpl implements Service {28 @Override29public void execute(String str) {30 System.out.println("execute invoke: " + str);31 }32 }3334class Interceptor1 implements MethodInterceptor {35 @Override36public Object invoke(MethodInvocation methodInvocation) throws Throwable {37 System.out.println("interceptor1,before invoke");38 Object ret = methodInvocation.proceed();39 System.out.println("interceptor1,after invoke");40return ret;41 }42 }4344class Interceptor2 implements MethodInterceptor {45 @Override46public Object invoke(MethodInvocation methodInvocation) throws Throwable {47 System.out.println("interceptor2,before invoke");48 Object ret = methodInvocation.proceed();49 System.out.println("interceptor2,after invoke");50return ret;51 }52 }xml⽂件配置:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:context="/schema/context"5 xmlns:aop="/schema/aop"6 xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/sprin 78<context:component-scan base-package="demo.spring"/>910<bean class="demo.spring.ServiceImpl" id="service"></bean>11<bean class="demo.spring.Interceptor1" id="interceptor1"></bean>12<bean class="demo.spring.Interceptor2" id="interceptor2"></bean>13<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy">14<property name="target" ref="service"/>15<property name="interceptorNames">16<list>17<value>interceptor1</value>18<value>interceptor2</value>19</list>20</property>21</bean>22</beans>结果:interceptor1,before invokeinterceptor2,before invokeexecute invoke: hello world!interceptor2,after invokeinterceptor1,after invoke可以看到拦截链的执⾏过程与拦截器顺序的关系。
AOP配置(含注解)详解

AOP配置(含注解)详解AOP(Aspect-Oriented Programming)是面向切面编程的缩写,是一种通过将横切关注点(cross-cutting concern)从业务逻辑代码中分离出来的编程思想和技术。
AOP通过在程序中定义切点(Join point)和通知(Advice),可以在不修改原有代码的情况下,对系统进行横向扩展,实现一些跨越多个对象和模块的功能。
AOP可以通过XML配置或者注解配置来实现,下面将以注解配置为例进行详细解析。
首先,我们需要在项目中引入相关的AOP依赖,如Spring AOP。
然后,我们需要在Spring的配置文件中启用AOP功能,这可以通过在配置文件中添加`<aop:aspectj-autoproxy/>`来实现。
这样,Spring就会自动扫描并自动生成代理类以实现AOP。
接下来,我们需要定义切点和通知。
切点是在程序中定义的一些特定的方法,它们可以被AOP框架所拦截。
通知则是在切点被拦截时执行的一段代码。
除了切面、切点和通知,AOP还涉及到一些其他的概念,如切入点、连接点和增强器。
切入点是一个或多个切点的集合,用于定义一组相关的切点。
连接点是在程序中与切点相匹配的特定位置,如方法的执行点。
增强器则是在通知被调用之前或之后,对连接点进行拦截并执行相应的通知。
总之,AOP通过在程序中定义切点和通知,可以实现对系统中特定方法的拦截和增强。
它可以很好地解耦系统的各个模块,并提供了一种便捷的方式来实现横切关注点的功能。
需要注意的是,AOP是一种非常强大和灵活的编程思想和技术,它可以用于很多方面,如日志记录、性能监控、安全检查等。
在使用AOP时,需要充分考虑系统的复杂性和可维护性,避免过度使用AOP,以免产生不必要的复杂性和难以维护的代码。
同时,需要合理地选择切点和通知,保持代码的简洁和可读性。
Spring中IOC和AOP的深入讲解

Spring中IOC和AOP的深⼊讲解前⾔Spring是⼀个开源框架,Spring是于2003 年兴起的⼀个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍⽣⽽来。
它是为了解决企业应⽤开发的复杂性⽽创建的。
Spring使⽤基本的JavaBean来完成以前只可能由EJB完成的事情。
然⽽,Spring的⽤途不仅限于服务器端的开发。
从简单性、可测试性和松耦合的⾓度⽽⾔,任何Java应⽤都可以从Spring中受益。
简单来说,Spring是⼀个轻量级的控制反转(IoC)和⾯向切⾯(AOP)的容器框架。
这篇⽂章主要讲 Spring 中的⼏个点,Spring 中的 IOC,AOP,下⼀篇说说 Spring 中的事务操作,注解和 XML 配置。
Spring 简介Spring 是⼀个开源的轻量级的企业级框架,其核⼼是反转控制 (IoC) 和⾯向切⾯ (AOP) 的容器框架。
我们可以把 Spring 看成是对象的容器,容器中可以包含很多对象,所以 Spring 有很多强⼤的功能。
⼀句话,Spring 是项⽬中对象的管家,负责管理项⽬中⽤到的所有对象。
所以在项⽬三层架构中,Spring 不属于某⼀特定层。
Spring 的 Hello World想要构建⼀个 Spring 的⼊门程序,我们需要导⼊ 4 个核⼼包和 2 个辅助包,创建⼀个实体类,最主要的是编写核⼼配置⽂件,applicationContext.xml 放在 src 下。
最后写⼀个测试类即可。
此时在测试类中我们不需要在使⽤ new 关键字去创建对象了。
这也正是 Spring 的作⽤所在,会⾃动给我创建对象。
上图展⽰的就是最基本的演⽰,也是很容易就理解了,配置⽂件中配置了 user 对象,我们通过加载配置⽂件来获取对象从⽽避免了使⽤ new 来创建。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于注解的Spring AOP的配置和使用AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
我们现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP就实现了把这些业务需求与系统需求分开来做。
这种解决的方式也称代理机制。
先来了解一下AOP的相关概念,《Spring参考手册》中定义了以下几个AOP的重要概念,结合以上代码分析如下:∙切面(Aspect):官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,在本例中,“切面”就是类TestAspect所关注的具体行为,例如,AServiceImpl.barA()的调用就是切面TestAspect所关注的行为之一。
“切面”在ApplicationContext 中<aop:aspect>来配置。
∙连接点(Joinpoint):程序执行过程中的某一行为,例如,UserService.get 的调用或者UserService.delete抛出异常等行为。
∙通知(Advice):“切面”对于某个“连接点”所产生的动作,例如,TestAspect 中对com.spring.service包下所有类的方法进行日志记录的动作就是一个Advice。
其中,一个“切面”可以包含多个“Advice”,例如ServiceAspect。
∙切入点(Pointcut):匹配连接点的断言,在AOP中通知和一个切入点表达式关联。
例如,TestAspect中的所有通知所关注的连接点,都由切入点表达式execution(* com.spring.service.*.*(..))来决定。
∙目标对象(Target Object):被一个或者多个切面所通知的对象。
例如,AServcieImpl和BServiceImpl,当然在实际运行时,Spring AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。
∙AOP代理(AOP Proxy):在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。
默认情况下,TargetObject实现了接口时,则采用JDK动态代理,例如,AServiceImpl;反之,采用CGLIB代理,例如,BServiceImpl。
强制使用CGLIB代理需要将 <aop:config>的 proxy-target-class属性设为true。
通知(Advice)类型:∙前置通知(Before advice):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。
ApplicationContext中在<aop:aspect>里面使用<aop:before>元素进行声明。
例如,TestAspect中的doBefore方法。
∙后置通知(After advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
ApplicationContext中在<aop:aspect>里面使用<aop:after>元素进行声明。
例如,ServiceAspect中的returnAfter方法,所以Teser中调用 UserService.delete抛出异常时,returnAfter方法仍然执行。
∙返回后通知(After return advice):在某连接点正常完成后执行的通知,不包括抛出异常的情况。
ApplicationContext中在<aop:aspect>里面使用<after-returning>元素进行声明。
∙环绕通知(Around advice):包围一个连接点的通知,类似Web中Servlet 规范中的Filter的doFilter方法。
可以在方法的调用前后完成自定义的行为,也可以选择不执行。
ApplicationContext中在<aop:aspect>里面使用<aop:around>元素进行声明。
例如,ServiceAspect中的around方法。
∙抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
ApplicationContext中在<aop:aspect>里面使用<aop:after-throwing>元素进行声明。
例如,ServiceAspect中的returnThrow方法。
注:可以将多个通知应用到一个目标对象上,即可以将多个切面织入到同一目标对象。
使用Spring AOP可以基于两种方式,一种是比较方便和强大的注解方式,另一种则是中规中矩的xml配置方式。
先说注解,使用注解配置Spring AOP总体分为两步,第一步是在xml文件中声明激活自动扫描组件功能,同时激活自动代理功能(同时在xml中添加一个UserService的普通服务层组件,来测试AOP的注解功能):<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/aop /schema/aop/spring-aop-3.1.xsd/schema/beans http://ww /schema/beans/spring-beans.xsd/schema/context http:// /schema/context/spring-context-3.0.xsd"><!-- 激活组件扫描功能,在包cn.ysh.studio.spring.aop及其子包下面自动扫描通过注解配置的组件 --><context:component-scan base-package="cn.ysh.studio.spring.ao p"/><!-- 激活自动代理功能 --><aop:aspectj-autoproxy proxy-target-class="true"/><!-- 用户服务对象 --><bean id="userService"class="cn.ysh.studio.spring.aop.servic erService"/></beans>第二步是为Aspect切面类添加注解:package cn.ysh.studio.spring.aop.aspect;import mons.logging.Log;import mons.logging.LogFactory;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.After;import ng.annotation.AfterReturning;import ng.annotation.AfterThrowing;import ng.annotation.Around;import ng.annotation.Aspect;import ng.annotation.Before;import ng.annotation.Pointcut;import ponent;/*** 系统服务组件Aspect切面Bean* @author Shenghany* @date 2013-5-28*///声明这是一个组件@Component//声明这是一个切面Bean@Aspectpublic class ServiceAspect{private final static Log log =LogFactory.getLog(ServiceAspec t.class);//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点@Pointcut("execution(* cn.ysh.studio.spring.aop.service..* (..))")public void aspect(){}/** 配置前置通知,使用在方法aspect()上注册的切入点* 同时接受JoinPoint切入点对象,可以没有该参数*/@Before("aspect()")public void before(JoinPoint joinPoint){if(log.isInfoEnabled()){("before "+ joinPoint);}}//配置后置通知,使用在方法aspect()上注册的切入点@After("aspect()")public void after(JoinPoint joinPoint){if(log.isInfoEnabled()){("after "+ joinPoint);}}//配置环绕通知,使用在方法aspect()上注册的切入点@Around("aspect()")public void around(JoinPoint joinPoint){long start =System.currentTimeMillis();try{((ProceedingJoinPoint) joinPoint).proceed();long end =System.currentTimeMillis();if(log.isInfoEnabled()){("around "+ joinPoint +"\tUs e time : "+(end - start)+" ms!");}}catch(Throwable e){long end =System.currentTimeMillis();if(log.isInfoEnabled()){("around "+ joinPoint +"\tUs e time : "+(end - start)+" ms with exception : "+ e.getMessage ());}}}//配置后置返回通知,使用在方法aspect()上注册的切入点@AfterReturning("aspect()")public void afterReturn(JoinPoint joinPoint){if(log.isInfoEnabled()){("afterReturn "+ joinPoint);}}//配置抛出异常后通知,使用在方法aspect()上注册的切入点@AfterThrowing(pointcut="aspect()", throwing="ex")public void afterThrow(JoinPoint joinPoint,Exception ex){if(log.isInfoEnabled()){("afterThrow "+ joinPoint +"\t"+ ex. getMessage());}}}测试代码:package cn.ysh.studio.spring.aop;import mons.logging.Log;import mons.logging.LogFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationCon text;import erService;import er;/*** Spring AOP测试* @author Shenghany* @date 2013-5-28*/public class Tester{private final static Log log =LogFactory.getLog(Tester.clas s);public static void main(String[] args){//启动Spring容器ApplicationContext context =new ClassPathXmlApplicat ionContext("applicationContext.xml");//获取service组件UserService service =(UserService) context.getBean(" userService");//以普通的方式调用UserService对象的三个方法User user = service.get(1L);service.save(user);try{service.delete(1L);}catch(Exception e){if(log.isWarnEnabled()){log.warn("Delete user : "+ e.getMessa ge());}}}}控制台输出如下:INFO [spring.aop.aspect.ServiceAspect:40] before execution(User cn.y erService.get(long))INFO [erService:19] getUser method ...INFO [spring.aop.aspect.ServiceAspect:60] around execution(User cn.y erService.get(long))Use time :42 m s!INFO [spring.aop.aspect.ServiceAspect:48] after execution(User cn.ys erService.get(long))INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(User erService.get(long))INFO [spring.aop.aspect.ServiceAspect:40] before execution(void cn.y erService.save(User))INFO [erService:26] saveUser method ...INFO [spring.aop.aspect.ServiceAspect:60] around execution(void cn.y erService.save(User))Use time :2 ms!INFO [spring.aop.aspect.ServiceAspect:48] after execution(void cn.ys erService.save(User))INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(void erService.save(User))INFO [spring.aop.aspect.ServiceAspect:40] before execution(boolean c erService.delete(long))INFO [erService:32] delete method ...INFO [spring.aop.aspect.ServiceAspect:65] around execution(boolean c erService.delete(long))Use time :5 ms with exception : spring aop ThrowAdvice演示INFO [spring.aop.aspect.ServiceAspect:48] after execution(boolean cn. erService.delete(long))INFO [spring.aop.aspect.ServiceAspect:74] afterReturn execution(bool ean erService.delete(long))WARN [studio.spring.aop.Tester:32]Delete user :Null return value f rom advice does not match primitive return type for: public boolean c erService.delete(long) throws java. lang.Exception可以看到,正如我们预期的那样,虽然我们并没有对UserSerivce类包括其调用方式做任何改变,但是Spring仍然拦截到了其中方法的调用,或许这正是AOP 的魔力所在。