您的位置:首页 > 编程语言 > ASP

Spring基于注解@AspectJ的AOP

2015-07-07 08:55 711 查看
Spring除了支持XML方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明。

但是用注解方式需要在XML启用对@AspectJ的支持<aop:aspectj-autoproxy/>,将在Spring上下文创建一个AnnotationAwareAspectJAutoProxyCreator类,它会自动代理一些Bean,这些Bean的方法需要与使用@Aspect注解的Bena中所定义的切点相匹配,而这些切点又是使用@Pointcut注解定义出来的,下面来看下例子(PS:我的例子都没有携带参数):


声明切入点

@AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut方法(方法必须是返回void类型)实现。
@Pointcut(value="切入点表达式", argNames = "参数名列表")  

public void pointcutName(……) {}  


声明通知

前置通知

使用org.aspectj.lang.annotation
包下的@Before注解声明;
@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")

后置返回通知

使用org.aspectj.lang.annotation
包下的@AfterReturning注解声明;
@AfterReturning(  

value="切入点表达式或命名切入点",  

pointcut="切入点表达式或命名切入点",  

argNames="参数列表参数名",  

returning="返回值对应参数名")


后置最终通知

使用org.aspectj.lang.annotation
包下的@After注解声明;
@After (  

value="切入点表达式或命名切入点",  

argNames="参数列表参数名")


后置异常通知

使用org.aspectj.lang.annotation
包下的@AfterThrowing注解声明

@AfterThrowing
(  

value="切入点表达式或命名切入点",  

pointcut="切入点表达式或命名切入点",  

argNames="参数列表参数名",  

throwing="异常对应参数名") 


package cn.com.ztz.spring.service;

public interface ShowService {
public void show();
}

package cn.com.ztz.spring.service;

public class ShowServiceImpl implements ShowService{
@Override
public void show() {
showBefore();
//showError();//异常测试 (后置异常通知)
showEnd();
}
public void showBefore(){
System.out.println("showBefore============");
}
public void showError(){
System.out.println("showError============");
throw new RuntimeException();
}
public void showEnd(){
System.out.println("showEnd===============");
}
}

package cn.com.ztz.spring.service;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AudienceAspect {
//定义切点
@Pointcut("execution(* cn.com.ztz.spring.service.ShowServiceImpl.show(..))")
public void performance(){
//该方法的内容不重要,该方法的本身只是个标识,供@Pointcut注解依附
}
//前置通知
@Before("performance()")
public void taskSeats(){
System.out.println("等候节目开始===");
}
//后置通知
@After("performance()")
public void applaud(){
System.out.println("鼓掌=========");
}
//后置异常通知
@AfterThrowing("performance()")
public void demandRefund(){
System.out.println("退钱离场======");
}
}
<!-- 启用@AspectJ支持 -->
<aop:aspectj-autoproxy/>
<bean id="show" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
<bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ShowService hs = ctx.getBean("show", ShowService.class);
System.out.println("======================================");
hs.show();
System.out.println("======================================");
}


运行测试方法控制台输出:

======================================

等候节目开始===

showBefore============

showEnd===============

鼓掌=========

======================================

注解环绕通知

像Spring基于XML的AOP一样,@AspectJ注解的使用不仅只限定与定义前置和后置通知类型。我们还可以创建环绕通知,使用环绕通知需要使用@Around。

@Around (  

value="切入点表达式或命名切入点",  

argNames="参数列表参数名")


public interface ShowService {
public void show(String param);
}
@Override
public void show(String param) {
System.out.println("around==========="+param);
}
@Aspect
public class AudienceAspect {
//定义切点
@Pointcut("execution(* cn.com.ztz.spring.service.ShowServiceImpl.show(..))")
public void performance(){
//该方法的内容不重要,该方法的本身只是个标识,供@Pointcut注解依附
}
@Around("performance()")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice===========");
Object retVal = pjp.proceed(new Object[] {"around"});
System.out.println("around after advice===========");
return retVal;
}
}
运行测试方法控制台输出:

======================================

around before advice===========

around===========around

around after advice===========

======================================

引入

@AspectJ风格的引入声明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents声明

@DeclareParents(  

value="AspectJ语法类型表达式",  

defaultImpl="引入接口的默认实现类")
 

package cn.com.ztz.spring.service;

public interface DeclareService {
public void declare();
}
package cn.com.ztz.spring.service;
public class DeclareServiceImpl implements DeclareService {
@Override
public void declare() {
System.out.println("declare=====================");
}
}
package cn.com.ztz.spring.service;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class AudienceAspect {
@DeclareParents(value="cn.com.ztz.spring.service.ShowServiceImpl+",
defaultImpl=cn.com.ztz.spring.service.DeclareServiceImpl.class)
private DeclareService declareService;}

public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
DeclareService hs = ctx.getBean("show", DeclareService.class);
System.out.println("======================================");
hs.declare();
System.out.println("======================================");
}


运行测试方法输出结果:

======================================

declare=====================

======================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息