Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明。
一、启用对@AspectJ的支持
Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:
<aop:aspectj-autoproxy/>
这样Spring就能发现@AspectJ风格的切面并且将切面应用到目标对象。
二、声明切面
@AspectJ风格的声明切面非常简单,使用@Aspect注解进行声明:
@Aspect() Public class Aspect{ …… }
然后将该切面在配置文件中声明为Bean后,Spring就能自动识别并进行AOP方面的配置:
<bean id="aspect" class="……Aspect"/>
该切面就是一个POJO,可以在该切面中进行切入点及通知定义,接着往下看吧。
三、声明切入点
@Pointcut(value="切入点表达式", argNames = "参数名列表") public void pointcutName(……) {}
value:指定切入点表达式;
argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。
pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。
@Pointcut(value="execution(* com.iflytek..*.sayAdvisorBefore(..)) && args(param)", argNames = "param") public void beforePointcut(String param) {}
定义了一个切入点,名字为“beforePointcut”,该切入点将匹配目标方法的第一个参数类型为通知方法实现中参数名为“param”的参数类型。
四、声明通知
@AspectJ风格的声明通知也支持5种通知类型:
1、前置通知
使用org.aspectj.lang.annotation 包下的@Before注解声明;
@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义。
2、后置返回通知
使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;
@AfterReturning( value="切入点表达式或命名切入点", pointcut="切入点表达式或命名切入点", argNames="参数列表参数名", returning="返回值对应参数名")
value:指定切入点表达式或命名切入点;
pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
argNames、returning:与Schema方式配置中的同义。
3、后置异常通知
使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明;
@AfterThrowing ( value="切入点表达式或命名切入点", pointcut="切入点表达式或命名切入点", argNames="参数列表参数名", throwing="异常对应参数名")
value:指定切入点表达式或命名切入点;
pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
argNames、throwing:与Schema方式配置中的同义。
4、后置最终通知
使用org.aspectj.lang.annotation 包下的@After注解声明;
@After ( value="切入点表达式或命名切入点", argNames="参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义;
5、环绕通知
使用org.aspectj.lang.annotation 包下的@Around注解声明;
@Around ( value="切入点表达式或命名切入点", argNames="参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义;
Demo
1、定义接口和实现,在此我们就使用Schema风格时的定义;
2、切面HelloWorldAnnotationAspect.java
package com.iflytek.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.DeclareParents; import org.aspectj.lang.annotation.Pointcut; import com.iflytek.service.IIntroductionService; /** * @author xdwang * * @create 2013-8-10 下午7:05:50 * * @email:xdwangiflytek@gmail.com * * @description 切面 * */ @Aspect//定义切面 public class HelloWorldAnnotationAspect { /** * @descrption 定义切入点 * @author xdwang * @create 2013-8-9下午7:08:40 * @param param */ @Pointcut(value = "execution(* com.iflytek..*.sayBefore(java.lang.String)) && args(param)", argNames = "param") public void beforePointcut(String param) { } /** * @descrption 前置通知 * @author xdwang * @create 2013-8-9下午7:08:18 * @param param */ @Before(value = "beforePointcut(param)", argNames = "param") public void beforeAdvice(String param) { System.out.println("===========before advice param:" + param); } /** * @descrption 后置返回通知 * @author xdwang * @create 2013-8-9下午7:09:04 * @param retVal */ @AfterReturning(value = "execution(* com.iflytek..*.sayBefore(..))", pointcut = "execution(* com.iflytek..*.sayAfterReturning(..))", argNames = "retVal", returning = "retVal") public void afterReturningAdvice(Object retVal) { System.out.println("===========after returning advice retVal:" + retVal); } /** * @descrption 后置异常通知 * @author xdwang * @create 2013-8-9下午7:09:45 * @param exception */ @AfterThrowing(value = "execution(* com.iflytek..*.sayAfterThrowing(..))", argNames = "exception", throwing = "exception") public void afterThrowingAdvice(Exception exception) { System.out.println("===========after throwing advice exception:" + exception); } /** * @descrption 后置最终通知 * @author xdwang * @create 2013-8-9下午7:09:55 */ @After(value = "execution(* com.iflytek..*.sayAfterFinally(..))") public void afterFinallyAdvice() { System.out.println("===========after finally advice"); } /** * @descrption 环绕通知 * @author xdwang * @create 2013-8-9下午7:10:41 * @param pjp * @return * @throws Throwable */ @Around(value = "execution(* com.iflytek..*.sayAround(..))") public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { System.out.println("===========around before advice"); Object retVal = pjp.proceed(new Object[] { "replace" }); System.out.println("===========around after advice"); return retVal; } @Around(value = "this(com.iflytek.service.IIntroductionService+)") public Object thisPointcut(ProceedingJoinPoint pjp) throws Throwable { System.out.println("===========around sssss advice"); Object retVal = pjp.proceed(); System.out.println("===========around ssss advice"); return retVal; } }
Resources/adviceAnnotation.xml
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy /> <bean id="helloWorldService" class="com.iflytek.service.impl.HelloWorldService" /> <bean id="aspect" class="com.iflytek.aop.HelloWorldAnnotationAspect" /> </beans>
Test
package com.iflytek.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.iflytek.service.IHelloWorldService; import com.iflytek.service.IIntroductionService; /** * @author xdwang * * @create 2013-8-9 下午7:58:22 * * @email:xdwangiflytek@gmail.com * * @description 测试 * */ public class AopTest { /** * @descrption 前置通知 * @author xdwang * @create 2013-8-9下午7:08:55 */ @Test public void testAnnotationBeforeAdvice() { System.out.println("======================================"); ApplicationContext ctx = new ClassPathXmlApplicationContext("adviceAnnotation.xml"); IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class); helloworldService.sayBefore("before"); System.out.println("======================================"); } /** * @descrption 后置返回通知 * @author xdwang * @create 2013-8-9下午7:09:28 */ @Test public void testAnnotationAfterReturningAdvice() { System.out.println("======================================"); ApplicationContext ctx = new ClassPathXmlApplicationContext("adviceAnnotation.xml"); IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class); helloworldService.sayAfterReturning(); System.out.println("======================================"); } /** * @descrption 后置异常通知 * @author xdwang * @create 2013-8-9下午7:09:39 */ @Test(expected = RuntimeException.class) public void testAnnotationAfterThrowingAdvice() { System.out.println("======================================"); ApplicationContext ctx = new ClassPathXmlApplicationContext("adviceAnnotation.xml"); IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class); helloworldService.sayAfterThrowing(); System.out.println("======================================"); } /** * @descrption 后置最终通知 * @author xdwang * @create 2013-8-9下午7:10:03 */ @Test(expected = RuntimeException.class) public void testAnnotationAfterFinallyAdvice() { System.out.println("======================================"); ApplicationContext ctx = new ClassPathXmlApplicationContext("adviceAnnotation.xml"); IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class); helloworldService.sayAfterFinally(); System.out.println("======================================"); } /** * @descrption 环绕通知 * @author xdwang * @create 2013-8-9下午7:10:15 */ @Test public void testAnnotationAroundAdvice() { System.out.println("======================================"); ApplicationContext ctx = new ClassPathXmlApplicationContext("adviceAnnotation.xml"); IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class); helloworldService.sayAround("haha"); System.out.println("======================================"); } }
切面、切入点、通知全部使用注解完成:
1)使用@Aspect将POJO声明为切面;
2)使用@Pointcut进行命名切入点声明,同时指定目标方法第一个参数类型必须是java.lang.String,对于其他匹配的方法但参数类型不一致的将也是不匹配的,通过argNames = "param"指定了将把该匹配的目标方法参数传递给通知同名的参数上;
3)使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点;
4)配置文件需要使用<aop:aspectj-autoproxy/>来开启注解风格的@AspectJ支持;
5)需要将切面注册为Bean,如“aspect”Bean;
6)测试代码完全一样。
结果:
1、 前置通知 ========================================== ===========before advice param:before ============say before ========================================== 2、后置返回通知 ====================================== ============after returning ===========after returning advice retVal:true 3、后置异常通知 ====================================== ============before throwing ===========after throwing advice exception:java.lang.RuntimeException 4、后置最终通知 ====================================== ============before finally ===========after finally advice 5、环绕通知 ====================================== ===========around before advice ===========around sssss advice ============around param:replace ===========around ssss advice ===========around after advice ======================================
五、引入
@AspectJ风格的引入声明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents声明:
@DeclareParents( value=" AspectJ语法类型表达式", defaultImpl=引入接口的默认实现类) private Interface interface;
value:匹配需要引入接口的目标对象的AspectJ语法类型表达式;与Schema方式中的types-matching属性同义;
private Interface interface:指定需要引入的接口;
defaultImpl:指定引入接口的默认实现类,没有与Schema方式中的delegate-ref属性同义的定义方式;
@DeclareParents(value = "com.iflytek..*.IHelloWorldService+", defaultImpl = com.iflytek.service.impl.IntroductionService.class) private IIntroductionService introductionService;
/** * @descrption 引入 * @author xdwang * @create 2013-8-9下午7:10:30 */ @Test public void testAnnotationIntroduction() { System.out.println("======================================"); ApplicationContext ctx = new ClassPathXmlApplicationContext("adviceAnnotation.xml"); IIntroductionService introductionService = ctx.getBean("helloWorldService", IIntroductionService.class); introductionService.induct(); System.out.println("======================================"); }
====================================== =========introduction ======================================
转自http://jinnianshilongnian.iteye.com/
相关推荐
Spring AOP的实现基于动态代理,对于接口实现类,它使用Java的`java.lang.reflect.Proxy`类来创建代理对象;对于没有接口的类,Spring使用CGLIB库生成子类。在运行时,Spring AOP会根据切面定义生成代理对象,然后...
@AspectJ是Spring AOP的一种注解驱动方式,它极大地简化了AOP的使用。本篇文章将深入探讨@AspectJ的使用方法和背后的原理。 首先,我们需要理解面向切面编程(AOP)的基本概念。AOP是一种编程范式,它允许开发者将...
**Spring的AOP实例——XML与@AspectJ双版本解析** Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统的交叉关注点,如日志、事务管理等。AOP的核心概念包括切面...
`springAOP2`可能是一个包含具体示例代码的目录。`基于@AspectJ配置Spring AOP之一 - 飞扬部落编程仓库-专注编程,网站,专业技术.htm`和其关联的`_files`目录可能包含了一个详细的教程或演示如何配置和运行@AspectJ的...
Spring AOP的实现主要有两种方式:一种是基于代理的AOP(Proxy-based AOP),另一种是基于AspectJ的AOP(AspectJ-based AOP)。基于代理的AOP是Spring默认的方式,它主要通过JDK动态代理或者CGLIB字节码生成技术来...
一个基于@AspectJ的spring2.0 AOP应用实例,很小很简单,没有任何额外信息,最适合AOP入门学习。使用log4j打印信息。把项目直接import进myeclipse就可以使用啦......
本实例将带你深入理解并实践Spring AOP与@AspectJ的结合使用。 首先,了解AOP的基本概念。面向切面编程是一种编程范式,它允许程序员定义“切面”,即跨越多个对象的行为或责任。这些切面可以包含业务逻辑、日志、...
Spring 提供了两种主要的 AOP 实现方式:基于代理的和基于 AspectJ 的。基于代理的方式是 Spring 默认的实现,它通过 JdkDynamicProxy 或 CGLIB 创建代理对象来实现切面。而基于 AspectJ 的方式则更为强大,它允许...
Spring AOP的核心类包括`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.framework.ProxyFactory`、`org.springframework.aop.aspectj.autoproxy.AspectJAutoProxyCreator`等。...
本教程将探讨如何在Spring中结合AspectJ实现AOP,包括基于XML配置和基于注解的方式。 **一、AOP基本概念** AOP的核心概念有切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)和引入...
总结起来,"spring-aop-jar"涉及了Spring框架中的面向切面编程模块,包括Spring AOP和AspectJ的集成。通过理解和熟练使用这些组件,开发者可以有效地解耦关注点,提高代码的可维护性和可扩展性。在实际项目中,结合...
默认情况下,Spring使用基于Java的代理,但对于需要在静态方法或非Spring管理对象上应用AOP的情况,可能需要使用CGLIB或AspectJ字节码代理。 5. **理解代理行为**:理解Spring AOP代理的工作方式很重要,因为这可能...
这里,`<aop:aspectj-autoproxy>`元素启用了基于注解的AOP代理,`<bean>`标签注册了我们的`LoggingAspect`类。 最后,当Spring启动时,它会自动检测到`LoggingAspect`类,并在合适的时候调用其定义的通知。现在,...
3. AspectJ集成:Spring还支持完全基于AspectJ的AOP,提供了更强大的表达式语言和更灵活的切面定义。 在给定的压缩包文件中,我们可以看到以下几个子文件: 1. Spring_AOP_DynProxy:这可能包含有关Spring动态代理...
在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员定义横切关注点,如日志、事务管理等,并将这些关注点与业务逻辑分离。`@Before`是Spring AOP中一个重要的通知类型,用于在目标方法执行前执行...
Spring AOP,即面向切面编程,是Spring框架的核心组件之一,它允许程序员在不修改原有业务代码的情况下,对程序进行功能增强。本篇文章将详细阐述Spring AOP的基本概念、种类、代理原理、通知类型以及切入点,帮助你...
- **`org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAdvisorFactory`**:处理基于注解的切面,创建顾问(advisor)对象。 - **`org.springframework.aop.aspectj.AspectJAroundAdvice`**:...