您的位置:首页 > 编程语言 > Java开发

NO.13 Spring AOP 注解

2018-02-27 20:22 190 查看
NO.13 Spring AOP 注解

AOP开发配置方式:(1)xml配置(2)注解

这里,我们对比xml配置方式,介绍注解方式。

注解方式,除业务类StuCardService之外,也需要日志的打印,即响应,通知LoggerAspect。

倘若采用注解方式,需要有扫描,将普通JavaBean扫描到IOC容器中
<context:component-scan base-package="com.xt.aop.anno"></context:component-scan>
。再把注解配置到StuCardServiceImpl上
@Service
,通过stuCardServiceImpl获取bean
StuCardService scs = ioc.getBean("stuCardServiceImpl",StuCardService.class);


使用Spring AOP 注解时,首先需要打开Spring注解的开关,通过标签开启自动扫描,并自动代理,剩下的就交给通知类,要表明通知类是一个Aspect,需要一个标签,使之称为IOC中的一个JavaBean。标签分三层四类,@Component,@Respository,@Service,@Controller,LoggerAspect不属于任一层,它就是把这些业务当作一条线切开,属于一个组件,类似于一个插件一样,用Component注解就可以了。要表明是一个通知类,需要加一个标签@Aspect

由上可知:

通知类注解步骤:

1、将通知类以组件的形式配置到IOC容器中,使用注解@Component

2、将当前日志打印组件标识为一个通知对象,使用注解@Aspect

那么,怎么拦截业务bean里的方法,去触发通知呢?

在xml配置中使用
<aop:pointcut expression="execution(* com.xt.spring.aop.xml.StuCardServiceImpl.*(..))" id="stuCardDeposit"/>
配置切点。

注解方式则通过
@Pointcut("execution(* com.xt.spring.aop.xml.StuCardServiceImpl.*(..))")
配置,那么就会自动地拦截StuCardServiceImpl中的所有方法,(..)代表匹配所有类型的参数,execution后的*代表匹配所有类型的返回值。

xml配置中的, 是对应到方法上的,注解方式可通过@Before,这个before与junit中的before不同,需要用到org.aspectj.lang.annotation.Before,这样就标识了这个方法为前置通知。

@Before("execution(* com.xt.spring.aop.xml.StuCardServiceImpl.deposit(..))")
public void beforeMethodAdvice(JoinPoint jp){
System.out.println("方法:"+ jp.getSignature().getName() + "被执行,前置通知被触发.......");
Object[] args = jp.getArgs();
}


打印结果:



对于后置返回通知,xml中配置了返回值
returning="result"
,这种情况,还能像前置通知和后置通知那样注解吗?答案是不可以,应配置为:

@AfterReturning(pointcut="execution(* com.xt.spring.aop.anno.StuCardServiceImpl.*(..))",returning="result")
public void afterReturningMethodAdvice(JoinPoint jp,Object result){
System.out.println("方法:"+ jp.getSignature().getName() + "被执行,后置返回通知被触发,返回值为" + result);
}


前置通知和后置通知的注解则是省略了pointcut。

环绕通知同前置通知和后置通知。

可得结果:

(由于参数已被改变)



异常通知类似后置返回通知。

@AfterThrowing(pointcut="execution(* com.xt.spring.aop.anno.StuCardServiceImpl.*(..))",throwing="e")
public void afterThrowingAdvice(JoinPoint jp, Exception e){
System.out.println("后置异常通知:方法:" + jp.getSignature().getName() + "抛出异常" + e);
}


由上可以观察到,每个注解都有配置切点,那么,能不能将切点抽象出来,配置成公用的呢?

xml中可配置
<aop:pointcut expression="execution(String com.xt.spring.aop.xml.StuCardServiceImpl.deposit(..))" id="stuCardDeposit"/>


注解同样可以配置:

@Pointcut("execution(* com.xt.spring.aop.anno.StuCardServiceImpl.*(..))")
public void loggerPointCut(){
}


这时,通知的注解引用方法名即可

@Before("loggerPointCut()")
@AfterReturning(pointcut="loggerPointCut()",returning="result")
@AfterThrowing(pointcut="loggerPointCut()",throwing="e")


倘若有多个通知类呢?LoggerAspect,LoggerAspect1

LoggerAspect,LoggerAspect1对com.xt.spring.aop.anno.StuCardServiceImpl.*(..)都有一定的拦截,那么有没有先后顺序呢?

测试可得结果为:



由此可知先执行了LoggerAspect,后执行了LoggerAspect1。

如果想先执行LoggerAspect1,该怎么办呢?

可在LoggerAspect,LoggerAspect1上加上注解@Order,Order里需要配置一个值,值越小,越靠前执行

@Order(0)
@Aspect
@Component
public class LoggerAspect1 {


@Order(1)
@Aspect
@Component
public class LoggerAspect {


可得结果:



概述为:如果存在多个通知类,而且需要设置运行的顺序,则需要@Order(值), 值的范围大于等于0 ,值越小越早执行。

以上就是AOP的注解形式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring aop开发 注解