spring中的增强类型
在spring中有两种增强方式:XML配置文件和注解配置。下面一次为大家讲解。
使用的是Aspectj第三方框架 纯POJO (在XML中配置节点)
使用@AspectJ,首先要保证所用的JDK 是5.0或以上版本
1)首先,创建一个切入点MyAspect,代码如下:
1 public class MyAspect { 2 // 前置通知 3 public void myBefore() { 4 System.out.println("这是前置增强"); 5 } 6 //前置通知带参 7 public void before(JoinPoint jp) { 8 System.out.println("前置通知方法before() jp = " + jp); 9 } 10 11 // 后置通知 12 public void myAfterReturning() { 13 System.out.println("这是后置增强"); 14 } 15 16 // 后置通知带参 17 public void afterReturing(String result) { 18 System.out.println("后置通知方法 result = " + result); 19 } 20 21 // 环绕通知 22 public Object around(ProceedingJoinPoint pjp) throws Throwable { 23 System.out.println("环绕通知方法,目标方法执行之前"); 24 // 执行目标方法 25 Object result = pjp.proceed(); 26 System.out.println("环绕通知方法,目标方法执行之后"); 27 return ((String) result).toUpperCase(); 28 } 29 30 // 异常通知 31 public void afterThrowing() { 32 System.out.println("异常通知方法"); 33 } 34 35 public void afterThrowing(Exception ex) { 36 System.out.println("异常通知方法 ex = " + ex.getMessage()); 37 } 38 39 // 最终通知 40 public void after() { 41 System.out.println("最终通知方法"); 42 } 43 }
2)applicationContext.xml中配置如下
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 8 //需要注意的是这里必须要引用aop命名空间,否则一切都是空谈~ 9 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 10 <!-- 目标对象 --> 11 <bean id="someService" class="entity.SomeServiceImpl"></bean> 12 13 <!-- 切面: --> 14 <bean id="myAspect" class="aop.MyAspect"></bean> 15 16 <aop:config> 17 <!--expression:切入点表达式 --> 18 <aop:pointcut expression="execution(public * *..ISomeService.doLog(..))" 19 id="beforePointcut" /> 20 <aop:aspect ref="myAspect"><!-- ref:指定切面 --> 21 <!-- method:指定切面类中的方法; pointcut-ref:指定定义的切点 --> 22 <!-- 前置增强 --> 23 <aop:before method="myBefore" pointcut-ref="beforePointcut" /> 24 <!-- 前置增强 带参 --> 25 <aop:before method="before(org.aspectj.lang.JoinPoint)" 26 pointcut-ref="beforePointcut" /> 27 <!-- 后置增强 --> 28 <aop:after-returning method="myAfterReturning" 29 pointcut-ref="beforePointcut" /> 30 <!-- 后置增强 带参 --> 31 <aop:after-returning method="afterReturing(java.lang.String)" 32 pointcut-ref="beforePointcut" returning="result" /> 33 <!-- 环绕增强 --> 34 <aop:around method="around" pointcut-ref="beforePointcut" /> 35 <!-- 异常增强 --> 36 <aop:after-throwing method="afterThrowing" 37 pointcut-ref="beforePointcut" /> 38 <!-- 异常增强 带参 --> 39 <aop:after-throwing method="afterThrowing(java.lang.Exception)" 40 pointcut-ref="beforePointcut" throwing="ex" /> 41 <!-- 最终增强 --> 42 <aop:after method="after" pointcut-ref="beforePointcut" /> 43 </aop:aspect> 44 </aop:config> 45 </beans>
3)运行结果如下:
2.使用注解定义增强
AspectJ是一个面向切面的框架,它扩展了Java语言,定义了AOP 语法,能够在编译期提供代码的织入
@AspectJ是AspectJ 5新增的功能,使用JDK 5.0 注解技术和正规的AspectJ切点表达式语言描述切面
Spring通过集成AspectJ实现了以注解的方式定义增强类,避开了在xml中的节点操作,大大减少了配置文件中的工作量
ps:在一个项目中,既有注解还有xml配置文件,那么注解优于xml配置文件而优先执行。
1)在切面中配置注解AOP增强
1 package aop; 2 import org.aspectj.lang.ProceedingJoinPoint; 3 import org.aspectj.lang.annotation.After; 4 import org.aspectj.lang.annotation.AfterReturning; 5 import org.aspectj.lang.annotation.AfterThrowing; 6 import org.aspectj.lang.annotation.Around; 7 import org.aspectj.lang.annotation.Aspect; 8 import org.aspectj.lang.annotation.Before; 9 10 //标示该类为切面(切入点表达式在这里不做讲解) 11 @Aspect 12 public class MyAspect { 13 14 // 前置通知 15 @Before(value = "execution(public * *..ISomeService.doLog(..))") 16 public void myBefore() { 17 System.out.println("这是前置增强"); 18 } 19 20 // 后置通知 21 @AfterReturning(value = "execution(public * *..ISomeService.doLog(..))") 22 public void myAfterReturning() { 23 System.out.println("这是后置增强"); 24 } 25 26 // 环绕增强 27 @Around(value = "execution(public * *..ISomeService.doLog(..))") 28 public void myAround(ProceedingJoinPoint pjp) throws Throwable { 29 System.out.println("这是环绕前置增强"); 30 31 pjp.proceed(); 32 33 System.out.println("这是环绕后置增强"); 34 } 35 36 // 异常增强 37 @AfterThrowing(value = "execution(public * *..ISomeService.doLog(..))") 38 public void myAfterThrowing() { 39 System.out.println("这是异常增强"); 40 } 41 42 // 最终增强 43 @After(value = "execution(public * *..ISomeService.doLog(..))") 44 public void myAfter() { 45 System.out.println("这是最终增强"); 46 } 47 }
2)在applicationContext.xml中配置一个自动代理节点
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 //一定要注意引用命名空间 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 xsi:schemaLocation=" 8 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 9 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 10 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 11 12 <!-- 目标对象 --> 13 <bean id="someService" class="entity.SomeServiceImpl"></bean> 14 15 <!-- 切面: --> 16 <bean id="myAspect" class="aop.MyAspect"></bean> 17 18 <!-- 自动代理:弄个标签就可以自动代理了,比之前繁琐的步骤简单多了 --> 19 <aop:aspectj-autoproxy/> 20 </beans>
3)输出结果
MyTest.java(上面的xml配置文件和注解都可以使用,只要对应目标对象的id/name就可以了)
public class MyTest { @Test public void Test1(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); ISomeService biz= //对应目标对象的id或者name属性 (ISomeService)ctx.getBean("someService"); biz.doLog(); biz.doTransaction(); System.out.println("success!"); } }