您好,登录后才能下订单哦!
这篇“Spring AOP如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring AOP如何使用”文章吧。
@Repository("userDao") public class UserDao { public void addUser() { System.out.println("???? 拦截的方法 addUser 开始执行"); } }
@Aspect @Component public class AnnotationAspect { // 定义切入点表达式, 使用一个返回值为 void、方法体为空的方法来命名切入点 @Pointcut("execution(* com.fairy.springmvc.aspectj.annotation.*.*(..))") private void customPointCut(){} // 前置通知 @Before("customPointCut()") public void myBefore(JoinPoint joinPoint){ System.out.print("前置通知:模拟执行权限检查..,"); System.out.print("目标类是:" + joinPoint.getTarget()); System.out.println(",被植入增强处理的目标方法为:" + joinPoint.getSignature().getName()); } // 后置通知 @AfterReturning(value="customPointCut()") public void myAfterReturning(JoinPoint joinPoint) { System.out.print("后置通知:模拟记录日志..,"); System.out.println("被植入增强处理的目标方法为:" + joinPoint.getSignature().getName()); } /** * 环绕通知 * ProceedingJoinPoint 是 JoinPoint的子接口,表示可执行目标方法 * 1.必须是 Object 类型的返回值 * 2.必须接收一个参数,类型为 ProceedingJoinPoint * 3.必须 throws Throwable */ @Around("customPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ // 开始 System.out.println("环绕开始:执行目标方法之前,模拟开启事务..,"); // 执行当前目标方法 Object obj = proceedingJoinPoint.proceed(); // 结束 System.out.println("环绕结束:执行目标方法之后,模拟关闭事务..,"); return obj; } /** * 异常通知处理 * @param joinPoint * @param e */ @AfterThrowing(value="customPointCut()",throwing="e") public void myAfterThrowing(JoinPoint joinPoint, Throwable e){ System.out.println("异常通知:出错了" + e.getMessage()); } // 最终通知 @After("customPointCut()") public void myAfter(){ System.out.println("最终通知:模拟方法结束后释放资源.."); } }
开启@AspectJ
的注解配置方式,有两种方式
1 在 xml
文件,添加以下配置:
<!-- 启动基于注解的声明式 AspectJ 支持 --> <aop:aspectj-autoproxy />
2 使用了 Java
代码风格的配置,则需使用 EnableAspectJAutoProxy
注解
示例如下
@Configuration @EnableAspectJAutoProxy @ComponentScan("com.fairy.springmvc") public class ApplicationConfig { .... }
public class TestCase { @Test public void testAnnotation() throws Exception { ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "spring-test.xml"); // 从容器中获得内容 UserDao userDao= (UserDao) applicationContext.getBean("userDao"); // 执行方法 userDao.addUser(); } }
运行结果如下:
环绕开始:执行目标方法之前,模拟开启事务..,
前置通知:模拟执行权限检查..,
目标类是:com.fairy.springmvc.aspectj.annotation.UserDao@4a699efa,
被植入增强处理的目标方法为:addUser
???? 拦截的方法 addUser 开始执行
后置通知:模拟记录日志..,被植入增强处理的目标方法为:addUser
最终通知:模拟方法结束后释放资源..
环绕结束:执行目标方法之后,模拟关闭事务..,
通过输出结果看出,符合预期。
@Repository("companyDao") public class CompanyDao { public void addCompany() { System.out.println("???? 真正的业务处理:add company ????"); } public void exception() throws Exception { throw new Exception("业务异常了"); } }
@Component("xmlAspectConfig") public class XmlAspect { public void printUnderscore() { System.out.println("------------------------------------------------"); } /** * 在核心业务执行前执行,不能阻止核心业务的调用 * @param joinPoint */ public void beforeAdvice(JoinPoint joinPoint) { printUnderscore(); System.out.println("1️⃣ 通知:beforeAdvice 执行开始"); System.out.println(" 执行核心业务逻辑前,可以做一些前置的安全性的检测等"); System.out.println(" 通知:beforeAdvice 执行结束"); printUnderscore(); } /** * 核心业务退出后,不管是正常结束还是异常退出,均执行此通知 * @param joinPoint */ public void afterAdvice(JoinPoint joinPoint) { printUnderscore(); System.out.println("4️⃣ 通知:afterAdvice 执行开始"); System.out.println(" 此处可以对返回值做进一步的处理"); System.out.println(" 通知:afterAdvice 执行结束"); } /** * 核心业务调用正常退出后,不管是否有返回值,只要是正常退出,都会执行此通知 * @param joinPoint */ public void afterReturningAdvice(JoinPoint joinPoint) { printUnderscore(); System.out.println("2️⃣ 通知:afterReturningAdvice 执行开始"); System.out.println(" 此处可以对返回值做进一步处理"); System.out.println(" 通知:afterReturningAdvice 执行结束"); } /** * 核心业务逻辑调用异常退出后,执行此通知,处理错误信息 * @param e */ public void afterThrowingAdvice(Exception e) { printUnderscore(); System.out.println("3️⃣ 通知:afterThrowingAdvice 执行开始"); System.out.println(" 错误信息:" + e.getMessage()); System.out.println(" 此处意味着,在核心业务逻辑出错时,捕获异常,并可以做一些日志记录相关的操作"); } /** * 手动控制调用核心业务逻辑,以及调用前和调用后的处理 * @param pjp */ public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { // 开始 System.out.println("5️⃣ 环绕开始:执行目标方法之前"); System.out.println(" 此处可以做类似于 Before Advice 的事情"); // 调用核心逻辑,执行当前目标方法 Object obj = pjp.proceed(); // 打印下划线 printUnderscore(); // 结束 System.out.println(" 此处可以做类似于 After Advice 的事情"); System.out.println("5️⃣ 环绕结束:执行目标方法之后"); return obj; } }
<!-- 基于 XML 文件的配置进行声明,注意和 aop:aspectj-autoproxy 的区别 --> <aop:config proxy-target-class="true"> <!-- 基于 aspect 配置一个完整的切面 --> <aop:aspect id="aspectXmlConfigExample" ref="xmlAspectConfig"> <!-- 切点配置,可以配置多个切点 --> <aop:pointcut id="xmlPointCut" expression="execution(* com.fairy.springmvc.aspectj.xml.CompanyDao.*(..))"/> <aop:after-returning method="afterReturningAdvice" pointcut-ref="xmlPointCut" /> <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="xmlPointCut" throwing="e"/> <aop:after method="afterAdvice" pointcut-ref="xmlPointCut" /> <aop:around method="aroundAdvice" pointcut-ref="xmlPointCut" /> <aop:before method="beforeAdvice" pointcut-ref="xmlPointCut" /> </aop:aspect> </aop:config>
注意:
值得注意的是
around
与before
和after
的执行顺序。3
者的执行顺序取决于在xml
中的配置顺序。
public class TestCase { @Test public void testAnnotation() throws Exception { ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "spring-test.xml"); CompanyDao companyDao = (CompanyDao) applicationContext.getBean("companyDao"); companyDao.addCompany(); // companyDao.exception(); } }
输出结果如下:
-------------------------------
5️⃣ 环绕开始:执行目标方法之前
此处可以做类似于 Before Advice 的事情
------------------------------------------------
1️⃣ 通知:beforeAdvice 执行开始
执行核心业务逻辑前,可以做一些前置的安全性的检测等
通知:beforeAdvice 执行结束
------------------------------------------------
???? 真正的业务处理:add company ????
------------------------------------------------
2️⃣ 通知:afterReturningAdvice 执行开始
此处可以对返回值做进一步处理
通知:afterReturningAdvice 执行结束
------------------------------------------------
4️⃣ 通知:afterAdvice 执行开始
此处可以对返回值做进一步的处理
通知:afterAdvice 执行结束
------------------------------------------------
此处可以做类似于 After Advice 的事情
5️⃣ 环绕结束:执行目标方法之后
结果符合预期。
以上就是关于“Spring AOP如何使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。