AspectJ基于注解的使用
AspectJ简介
AspectJ是一个基于Java语言的AOP框架,一般
其主要用途:自定义开发
一般情况下spring自动生成代理,要配置aop,
首先确定目标类,aspectj 切入点表达式,需要导入jar包
spring-framework-3.0.2.RELEASE-dependenciesorg.aspectjcom.springsource.org.aspectj.weaver1.6.8.RELEASE
除了以上这个关键包,还有spring所需的5个基础包,以及其他三个包,具体情况如下图:
在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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 1.扫描 注解类 --> <context:component-scan base-package="com.xk.proxy.aspectJ_zhujie"></context:component-scan> </beans>
接着在service层用注解替换原先xml文件中的Bean
@Service("userServiceId") public class UserServiceImpl implements UserService { }
替换
<bean id="userServiceId" class="xxx.xxx.UserServiceImpl"></bean>
在切面类中用注解替换相应Bean
@Component public class MyAspect { }
替换
<bean id="myAspectId" class="xxx.xxx.xxx.aspectJ.MyAspect"></bean>
接着必须要进行aspectj 自动代理配置,否则即使声明了切面,也无法获取切面类中的方法
<!-- 1.扫描 注解类 --> <context:component-scan base-package="xxx.xxx.xxx.aspectJ_zhujie"></context:component-scan>
添加注解@Aspect ,声明切面,以获取切面方法
@Component @Aspect public class MyAspect { }
注解@Aspect替换了
<aop:aspect ref="myAspectId">
<aop:aspect> 将切面类 声明“切面”,从而获得通知(方法) ref 切面类引用
接着替换 公共切入点
<aop:pointcut expression="execution(* xxx.xxx.proxy.aspectJ.UserServiceImpl.*(..))" id="myPointCut"/>
这里涉及到了切入点表达式
execution()用于描述方法
语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
修饰符,一般省略
返回值,不能省略,
方法名,不能省略
‘ * ’表示任意
(参数)
() 表示无参
(..) 表示参数任意
用注解替换为
//声明公共切入点 @Pointcut("execution(* xxx.xxx.proxy.aspectJ.UserServiceImpl.*(..))") private void myPointCut(){ }
这里我用的是环绕通知类型,所以替换环绕
<aop:around method="myAround" pointcut-ref="myPointCut"/>
@Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("前"); //手动执行目标方法 Object obj = joinPoint.proceed(); System.out.println("后"); return obj; }
最后替换抛出异常
<aop:after-throwing method="myAfterThrowing" pointcut="execution(* xxx.xxx.UserServiceImpl.*(..))" throwing="e"/>
@AfterThrowing(value="execution(* xxx.xxx.UserServiceImpl.*(..))" ,throwing="e") public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ System.out.println("抛出异常通知 : " + e.getMessage()); }
最终切面类:
/** * 切面类,可含有多个通知 */ @Component @Aspect public class MyAspect { //切入点当前有效 //@Before("execution(*xxx.xxx.UserServiceImpl.*(..))") public void myBefore(JoinPoint joinPoint){ System.out.println("前置通知 : " + joinPoint.getSignature().getName()); } //声明公共切入点 @Pointcut("execution(*xxx.xxx.UserServiceImpl.*(..))") private void myPointCut(){ } // @AfterReturning(value="myPointCut()" ,returning="ret") public void myAfterReturning(JoinPoint joinPoint,Object ret){ System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret); } // @Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("前"); //手动执行目标方法 Object obj = joinPoint.proceed(); System.out.println("后"); return obj; } // @AfterThrowing(value="execution(* xxx.xxx.UserServiceImpl.*(..))" ,throwing="e") public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ System.out.println("抛出异常通知 : " + e.getMessage()); } @After("myPointCut()") public void myAfter(JoinPoint joinPoint){ System.out.println("最终通知"); } }
最终spring配置:
<!-- 1.扫描 注解类 --> <context:component-scan base-package="com.xk.proxy.aspectJ_zhujie"></context:component-scan> <!-- 2.确定 aop注解生效 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
aop注解总结:
@Aspect 声明切面,修饰切面类,从而获得 通知。
通知
@Before 前置
@AfterReturning 后置
@Around 环绕
@AfterThrowing 抛出异常
@After 最终
切入点
@PointCut ,修饰方法 private void xxx(){} 之后通过“方法名”获得切入点引用