Spring中配置@AspectJ
对@AspectJ支持可以使用XML或java风格的配置
确保AspectJ的aspectjweaver.jar库包含在应用程序(版本1.6.8或更高版本)的classpath中
aspect
@AspectJ切面使用@Aspect注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用
用@Aspect注解的类可以有方法和字段,他们也可能包括切入点(pointcout),通知(Advice)和引入(introduction)声明
@Aspect注解是不能够通过类路径自动检测发现的,所以需要配合使用@component注释或者在xml配置bean
一个类中的@Aspect注解标识它为一个切面,并且将自己从自动代理中排除。
pointcut
组合pointcut
切入点表达式可以通过&&、||和!进行组合,也可以通过名字引用切入点表达式
通过组合,可以建立更加复杂的切入点表达式
定义良好的pointcuts
AspectJ是编译期的AOP
检查代码并匹配连接点与切入点的代价是昂贵的
一个好的切入点应该包括以下几点
-选择特定类型的连接点,如execution,get,set,call,handler
-确定连接点范围,如:winthin,withincode
-匹配上下文信息,如:this,target,@annotation
After returning advice
方法结束后执行
After(finally)advice
最终通知必须准备处理正常和异常俩种返回情况,它通常用于释放资源
Around avice
环绕通知使用@Around注解来声明,通知方法的第一个参数必须是ProceedingJoinPoint类型
在通知内部调用ProceedingJoinPoint的proceed()方法会导致执行真正的方法,传入一个Object[]对象,数组中的值将被作为参数传递给方法
例子:
配置:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
">
<context:component-scan base-package="com.txr.AspectJ"/>
<aop:aspectj-autoproxy/>
</beans>
AspectEX类
package com.txr.AspectJ;
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.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AspectEx {
@Pointcut("execution(* com.txr.AspectJ.*Biz.*(..))")
public void pointcut(){}
@Pointcut("within(com.txr.AspectJ.*)")
public void bizPointcut(){}
//@Before("pointcut()")
@Before("execution(* com.txr.AspectJ.*Biz.*(..))")
public void before()
{
System.out.println("Before");
}
@AfterReturning(pointcut="bizPointcut()",returning="returnValue")
public void afterReturning(Object returnValue){
System.out.println("AfterReturning : "+returnValue);
}
@AfterThrowing(pointcut="pointcut()",throwing="e")
public void afterThrowing(RuntimeException e)
{
System.out.println("AfterThrowing : "+e.getMessage());
}
@After("pointcut()")
public void after()
{
System.out.println("After");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("Around 1.");
Object obj=pjp.proceed();
System.out.println("Around 2.");
System.out.println("Around : "+obj);
return obj;
}
}
TxrBiz类
package com.txr.AspectJ;
import org.springframework.stereotype.Service;
@Service
public class TxrBiz {
public String save(String arg)
{
System.out.println("TxrBiz save:"+arg);
//throw new RuntimeException("这是个异常");
return "Save success!";
}
}
测试类:
package AutoWiring;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.txr.AspectJ.TxrBiz;
public class TestAspect {
private ApplicationContext context=null;
@Before
public void init(){
context=new ClassPathXmlApplicationContext("com/txr/resource/spring-ioc.xml");
}
@Test
public void test()
{
TxrBiz biz=(TxrBiz) context.getBean("txrBiz");
biz.save("txr");
}
}
测试结果:
Around 1.
Before
TxrBiz save:txr
Around 2.
Around : Save success!
After
AfterReturning : Save success!