使用AspectJ实现AOP
注解方式
XML方式
AspectJ是一个基于Java语言的AOP框架
Spring2.0后新增了对AspectJ切点表达式支持
@AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式开发AOP
使用AspectJ需要导入Spring AOP和AspectJ相关jar包
spring-aop-4.2.4.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
spring-aspects-4.2.4.RELEASE.jar
com.springsource.org.aspectj-weaver-1.6.8.RELEASE.jar
注解开发:环境准备
<?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" 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"> <!--开启AspectJ自动代理--> < aop:aspectj-autoproxy /> </beans>
@AspectJ提供不同的通知类型
-
@Before前置通知,相当于BeforeAdvice
-
@AfterReturning后置通知,相当于AfterReturningAdvice
-
@Around环绕通知,相当于Methodinterceptor
-
@AfterThrowing异常抛出通知,相当于ThrowAdvice
-
@After最终final通知,不管是否异常,该通知都会被执行
-
@DeclareParents引介通知,相当于IntroductionInterceptor
在通知中通过value属性定义切点
通过execution函数,可以定义切点的方法切入
语法:——execution(<访问修饰符>?<返回方法><方法名>(<参数>)<异常>)
●例如 一匹配所有类public方法execution(public * *..)) *—匹配指定包下所有类方法execution( com.imooc.dao. (..))不包含子包
execution( com.imooc.dao..(.) ..表示包、 子孙包下所有类 一匹配指定类所有方法execution( com.imooc.service.UserService.(.l)* 一匹配实现特定接口所有类方法 execution( com.imooc.dao.GenericDAO+.(..)) 一匹配所有save开头的方法execution( save..))
1.@Before前置通知:
@Aspect public class MyAspectAnnotation { @Before(value="execution(* com.imooc.aspectj.demo1.ProductDao.*(..))") public void before() { System.out.println("前置通知"); } }
可以在方法中传入JoinPoint对象,用来获得切点信息
//要增强的代码: @Before ("execution(* com.imooc.spring.demo1.UserDao.save(..))") public void before (JoinPoint joinPoint) { System.out.println("========前置通知======" + joinPoint) ; }
2.@AfterReturning后置通知
@AfterReturning(value="execution(* com.imooc.aspectj.demo1.ProductDao.update(..))", returning = "result") public void afterReturning(Object result) { System.out.println("========后置通知========"); System.out.println(result); }
3.@Around环绕通知
-
around方法的返回值就是目标代理方法执行返回值
-
参数为ProceedingJoinPoint可以调用拦截目标方法执行
@Around ("execution(* com.imooc.spring.demo1.UserDao.delete(..)) ") public object around (ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("========环绕前通知======") ; object obj = joinPoint .proceed() ; System.out.println("========环绕后通知======") ; return obj; }
如果不调用ProceedingJoinPoint的proceed方法,那么目标方法就被拦截了。
4.@AfterThrowing异常抛出通知
-
通过设置throwing属性,可以设置发生异常对象参数
@AfterThrowing (value="execution(* com.imooc.spring .demo1.UserDao.find(..))", throwing="e") public void afterThrowing (Throwable e) { System.out.println("=======异常抛出通知======"+e . getMessage()) ; }
5.@After 最终通知
-
无论是否出现异常,最终通知总是会被执行的
@After (value="execution (* com.imooc.spring.demo1.UserDao.findAll(..))") public void after() { System. out. println("=======最终通知======"); }