春季AOP 方面J注释示例
如果您不熟悉Spring AOP术语,则可以通过 弹簧面向方面的编程(AOP)教程.
以下是AspectJ批注,我们将使用它们来实现Spring AOP。
@Aspect: 将一个类声明为Aspect。
用于创建建议的注释为:
@Before: @Before注释用于创建 咨询之前。它在实际方法执行之前执行(加入点)
@AfterReturning: 该注释用于创建 退货建议。它在方法执行完成后执行,没有任何异常。
@AfterThrowing: 该注释用于创建 提出建议后, 如果方法因抛出异常而退出,则执行该命令。
@之后: 该注释用于创建 经过咨询, 它会在方法执行后执行,无论结果如何。
@Around: 该注释用于创建 围绕建议, 它在连接点之前和之后执行。
现在这可能会令人困惑,但是一旦实现了示例,就很清楚了。
@之前:
假设您有一些业务逻辑类(商业逻辑.java),并且您想在执行此类的getBusinessLogic方法之前进行日志记录。
1 2 3 4 5 6 7 8 9 10 11 12 |
包 组织.Arpit.爪哇2blog; 上市 类 商业逻辑 { 上市 虚空 getBusinessLogic() { 系统.出.打印(“ *****************”); 系统.出.打印(“在业务逻辑方法中”); 系统.出.打印(“ *****************”); } } |
现在我们将创建方面类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
包 组织.Arpit.爪哇2blog; 进口 组织.方面.郎.JoinPoint; 进口 组织.方面.郎.注解.方面; 进口 组织.方面.郎.注解.之前; @方面 上市 类 记录方面 { @之前(“执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))”) 上市 虚空 loggingBeforeBusinessLogic(JoinPoint joinPoint) { 系统.出.打印(“ loggingBeforeBusinessLogic()正在运行!”); 系统.出.打印(“执行方法之前:” + joinPoint.getSignature().getName()); } } |
执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))是切入点表达式。它表示在执行BusinessLogic类的getBusinessLogic方法之前执行loggingBeforeBusinessLogic方法。
让我们在spring-config.xml中对上述bean进行xml配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<豆子 XML格式文件ns="http://www.springframework.org/schema/beans" XML格式文件ns:si="http://www.w3.org/2001/XMLSchema-instance" XML格式文件ns:哎呀="http://www.springframework.org/schema/aop" si:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <哎呀:方面-自代理 /> <豆 ID=“商业逻辑” 类=“ 组织.arpit.java2blog.BusinessLogic”> </豆> <!- 方面 -> <豆 ID=“ logAspect” 类=“ 组织.arpit.java2blog.LoggingAspect” /> </豆子> |
创建名为SpringAOPMain的主类以执行应用程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
包 组织.Arpit.爪哇2blog; 进口 组织.弹簧框架.语境.ApplicationContext; 进口 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext; 上市 类 弹簧AOPMain { 上市 静态的 虚空 主要(串[] args) { ApplicationContext appContext = 新 ClassPathXmlApplicationContext(“ 弹簧-config.xml”); 商业逻辑 商业逻辑 = (商业逻辑) appContext.getBean(“商业逻辑”); 商业逻辑.getBusinessLogic(); } } |
当您运行上述程序时,将获得以下输出:
1 2 3 4 5 6 7 8 9 10 11 |
七月 21, 2016 10:01:14 下午 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext 准备刷新 信息: 提神醒脑 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext@24174be7: 启动 日期 [周四 七月 21 22:01:14 IST 2016]; 根 的 语境 等级制 七月 21, 2016 10:01:14 下午 组织.弹簧框架.豆子.厂.XML格式文件.XmlBeanDefinitionReader loadBeanDefinitions 信息: 载入中 XML格式 豆 定义 从 类 路径 资源 [弹簧-配置.XML格式文件] loggingBeforeBusinessLogic() 是 跑步! 之前 执行 的 方法 : getBusinessLogic ***************** 在 商业 逻辑 方法 ***************** |
@后:
我用@After注释方法替换了LoggingAspect.java中的@Before方法,该方法将在执行实际业务逻辑后执行,因此 记录方面.java 看起来像这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
包 组织.Arpit.爪哇2blog; 进口 组织.方面.郎.JoinPoint; 进口 组织.方面.郎.注解.方面; 进口 组织.方面.郎.注解.后; @方面 上市 类 记录方面 { @后(“执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))”) 上市 虚空 loggingAfterBusinessLogic(JoinPoint joinPoint) { 系统.出.打印(“ loggingAfterBusinessLogic()正在运行!”); 系统.出.打印(“执行方法后:” + joinPoint.getSignature().getName()); } } |
再次运行SpringAOPMain.java时,将获得以下输出:
1 2 3 4 5 6 7 8 9 10 11 |
七月 21, 2016 10:24:26 下午 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext 准备刷新 信息: 提神醒脑 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext@75783d33: 启动 日期 [周四 七月 21 22:24:26 IST 2016]; 根 的 语境 等级制 七月 21, 2016 10:24:26 下午 组织.弹簧框架.豆子.厂.XML格式文件.XmlBeanDefinitionReader loadBeanDefinitions 信息: 载入中 XML格式 豆 定义 从 类 路径 资源 [弹簧-配置.XML格式文件] ***************** 在 商业 逻辑 方法 ***************** loggingAfterBusinessLogic() 是 跑步! 后 执行 的 方法 : getBusinessLogic |
如您在上面的输出中看到的那样,在getBusinessLogic方法之后执行loggingAfterBusinessLogic
@AfterReturning:
我在上面的LoggingAspect.java中用@AfterReturning替换@After。此方法将在实际业务逻辑执行后执行,但前提是成功返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
包 组织.Arpit.爪哇2blog; 进口 组织.方面.郎.JoinPoint; 进口 组织.方面.郎.注解.方面; 进口 组织.方面.郎.注解.返回后; @方面 上市 类 记录方面 { @返回后(“执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))”) 上市 虚空 loggingAfterBusinessLogic(JoinPoint joinPoint) { 系统.出.打印(“ loggingAfterBusinessLogic()正在运行!”); 系统.出.打印(“执行方法后:” + joinPoint.getSignature().getName()); } } |
再次运行SpringAOPMain.java时,将获得以下输出:
1 2 3 4 5 6 7 8 9 10 11 |
七月 21, 2016 10:24:26 下午 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext 准备刷新 信息: 提神醒脑 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext@75783d33: 启动 日期 [周四 七月 21 22:24:26 IST 2016]; 根 的 语境 等级制 七月 21, 2016 10:24:26 下午 组织.弹簧框架.豆子.厂.XML格式文件.XmlBeanDefinitionReader loadBeanDefinitions 信息: 载入中 XML格式 豆 定义 从 类 路径 资源 [弹簧-配置.XML格式文件] ***************** 在 商业 逻辑 方法 ***************** loggingAfterBusinessLogic() 是 跑步! 后 执行 的 方法 : getBusinessLogic |
@AfterThrowing:
让我们再添加一个带有@AfterThrowing批注的方法。如果getBusinessLogic方法中发生任何异常,它将执行。
记录方面.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
包 组织.Arpit.爪哇2blog; 进口 组织.方面.郎.JoinPoint; 进口 组织.方面.郎.注解.返回后; 进口 组织.方面.郎.注解.投掷后; 进口 组织.方面.郎.注解.方面; @方面 上市 类 记录方面 { @返回后(“执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))”) 上市 虚空 loggingAfterBusinessLogic(JoinPoint joinPoint) { 系统.出.打印(“ loggingAfterBusinessLogic()正在运行!”); 系统.出.打印(“执行方法后:” + joinPoint.getSignature().getName()); } @投掷后(“执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))”) 上市 虚空 loggingAfterBusinessLogicException(JoinPoint joinPoint) { 系统.出.打印(“ getBusinessLogic方法中发生异常”); } } |
现在从getBusinessLogic抛出RuntimeException来测试@AfterThrowing异常。 商业逻辑.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
包 组织.Arpit.爪哇2blog; 上市 类 商业逻辑 { 上市 虚空 getBusinessLogic() { 系统.出.打印(“ *****************”); 系统.出.打印(“在业务逻辑方法中”); 系统.出.打印(“ *****************”); 扔 新 RuntimeException(); } } |
运行SpringAOPMain.java时,将获得以下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
七月 21, 2016 10:34:55 下午 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext 准备刷新 信息: 提神醒脑 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext@739474: 启动 日期 [周四 七月 21 22:34:55 IST 2016]; 根 的 语境 等级制 七月 21, 2016 10:34:55 下午 组织.弹簧框架.豆子.厂.XML格式文件.XmlBeanDefinitionReader loadBeanDefinitions 信息: 载入中 XML格式 豆 定义 从 类 路径 资源 [弹簧-配置.XML格式文件] ***************** 在 商业 逻辑 方法 ***************** 例外 发生了 在 getBusinessLogic 方法 例外 在 线 “主要” 爪哇.郎.RuntimeException 在 组织.Arpit.爪哇2blog.商业逻辑.getBusinessLogic(商业逻辑.爪哇:9) 在 组织.Arpit.爪哇2blog.商业逻辑$$FastClassBySpringCGLIB$$3d288cb4.invoke() 在 组织.弹簧框架.cglib.代理.方法代理.调用(方法代理.爪哇:204) 在 组织.弹簧框架.哎呀.构架.CglibAopProxy$CglibMethodInvocation.调用Joinpoint(CglibAopProxy.爪哇:717) 在 组织.弹簧框架.哎呀.构架.ReflectiveMethodInvocation.继续(ReflectiveMethodInvocation.爪哇:157) 在 组织.弹簧框架.哎呀.构架.适配器.返回通知拦截器之后.调用(返回通知拦截器之后.爪哇:52) 在 组织.弹簧框架.哎呀.构架.ReflectiveMethodInvocation.继续(ReflectiveMethodInvocation.爪哇:179) 在 组织.弹簧框架.哎呀.方面.方面JAfterThrowingAdvice.调用(方面JAfterThrowingAdvice.爪哇:58) 在 组织.弹簧框架.哎呀.构架.ReflectiveMethodInvocation.继续(ReflectiveMethodInvocation.爪哇:179) 在 组织.弹簧框架.哎呀.拦截器.ExposeInvocationInterceptor.调用(ExposeInvocationInterceptor.爪哇:92) 在 组织.弹簧框架.哎呀.构架.ReflectiveMethodInvocation.继续(ReflectiveMethodInvocation.爪哇:179) 在 组织.弹簧框架.哎呀.构架.CglibAopProxy$动态建议拦截器.截距(CglibAopProxy.爪哇:653) 在 组织.Arpit.爪哇2blog.商业逻辑$$增强剂By 弹簧CGLIB$$1fbd989f.getBusinessLogic() 在 组织.Arpit.爪哇2blog.弹簧AOPMain.主要(弹簧AOPMain.爪哇:10) |
如您所见,由于业务逻辑中存在异常,所以执行了loggingAfterBusinessLogicException。
@周围:
使用@Around的方法将在执行业务逻辑之前和之后被调用。
您需要调用ProceedingJoinPoint的引用并调用proce方法来执行实际的业务逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
包 组织.Arpit.爪哇2blog; 进口 组织.方面.郎.继续加入积分; 进口 组织.方面.郎.注解.周围; 进口 组织.方面.郎.注解.方面; @方面 上市 类 记录方面 { @周围(“执行(* 组织.arpit.java2blog.BusinessLogic.getBusinessLogic(..))”) 上市 虚空 loggingAroundBusinessLogic(继续加入积分 joinPoint) 抛出 可投掷 { 系统.出.打印(“在调用实际业务逻辑之前”); //在运行实际业务逻辑之前 joinPoint.继续(); //执行业务逻辑方法 系统.出.打印(“调用实际的业务逻辑之后”); //运行实际的业务逻辑之后 } } |
运行SpringAOPMain.java时,将获得以下输出:
1 2 3 4 5 6 7 8 9 10 11 |
七月 21, 2016 11:04:10 下午 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext 准备刷新 信息: 提神醒脑 组织.弹簧框架.语境.支持.ClassPathXmlApplicationContext@739474: 启动 日期 [周四 七月 21 23:04:10 IST 2016]; 根 的 语境 等级制 七月 21, 2016 11:04:10 下午 组织.弹簧框架.豆子.厂.XML格式文件.XmlBeanDefinitionReader loadBeanDefinitions 信息: 载入中 XML格式 豆 定义 从 类 路径 资源 [弹簧-配置.XML格式文件] 之前 呼唤 实际 商业 逻辑 ***************** 在 商业 逻辑 方法 ***************** 后 呼唤 实际 商业 逻辑 |