Spring AOP方法分析

此示例显示如何配置Spring AOP方法概要分析。我们可以在任何服务(或其他)类中使用Spring AOP和任何方法,而无需在任何服务类中编写任何一行分析代码。面向方面编程(AOP)允许我们将(通常是重复的和样板)分析代码与服务代码分开。

目录[ 隐藏 ]

  • 1 Spring AOP方法分析

    • 1.1 Spring AOP方法分析项目结构
    • 1.2 Spring AOP Maven依赖项
    • 1.3 Spring Service类(待分析)
    • 1.4 Spring AOP Profiler类
    • 1.5 Spring AOP配置XML
    • 1.6 Spring AOP方法分析测试类

Spring AOP方法分析

我们只在一个单独的类(SimpleProfiler.java)中编写我们的探查器代码一次,这就是全部,其余的只有AOP配置spring.xml才能完成工作。

因此,我们可以对以下方法进行方法分析。

  1. 分析任何(服务)类,
  2. 没有触及(服务)类的代码,
  3. 通过Spring-AOP方法。

Spring AOP方法分析项目结构

Spring AOP Maven依赖项

我们将首先查看我们的pom.xml文件,了解所有必需的依赖项及其版本。我们在这个例子中使用Spring 4。


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>hu.daniel.hari.learn.spring</groupId><artifactId>Tutorial-SpringAop-Profiling</artifactId><version>1.0</version><packaging>jar</packaging><properties><!-- Generic properties --><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.7</java.version><!-- SPRING --><spring.version>4.0.0.RELEASE</spring.version></properties><dependencies><!-- Spring (includes spring-aop)--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- AspectJ (required spring-aop dependency) --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.5</version></dependency><!-- LOG --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies><build><plugins><!-- This plugin is needed to define the java version in maven project. --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>${java.version}</source><target>${java.version}</target></configuration></plugin></plugins></build></project>
  • 我们需要spring-context作为Spring依赖。
  • spring-aop还带有spring-context作为它的依赖库,所以不需要添加它。
  • aspectjweaver是spring-aop的依赖项,但我们必须添加它,因为它没有为spring-aop明确定义。

Spring Service类(待分析)

我们首先编写我们的服务类,它有模拟短进程和长进程的方法,还有一个抛出异常的方法。


package hu.daniel.hari.learn.spring.aop.profiling.service;import org.springframework.stereotype.Component;/*** Example service class that we want to profile through AOP.* (Notice that no need to insert any line of profiling code!)* * @author Daniel Hari*/
@Component
public class FooService {public void doShortJob() {sleep(10l);}public void doLongJob() {sleep(300l);}public void doSomethingThatThrowsException() {throw new RuntimeException("Simulated Exception.");}private void sleep(long millis) {try {Thread.sleep(millis);} catch (InterruptedException e) {e.printStackTrace();}}
}

请注意,我们没有在服务类中放置任何分析代码。

Spring AOP Profiler类

我们的探查器类可以简单地测量方法执行的处理时间。


package hu.daniel.hari.learn.spring.aop.profiling.core.profiler;import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
import org.springframework.util.StopWatch.TaskInfo;/*** Our profiler that* logs process time, and remark if process had exception.* * @author Daniel Hari*/
public class SimpleProfiler {/*** Spring AOP 'around' reference method signature is bounded like this, the* method name "profile" should be same as defined in spring.xml aop:around* section.**/public Object profile(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {StopWatch stopWatch = new StopWatch();stopWatch.start(proceedingJoinPoint.toShortString());boolean isExceptionThrown = false;try {// execute the profiled methodreturn proceedingJoinPoint.proceed();} catch (RuntimeException e) {isExceptionThrown = true;throw e;} finally {stopWatch.stop();TaskInfo taskInfo = stopWatch.getLastTaskInfo();// Log the method's profiling resultString profileMessage = taskInfo.getTaskName() + ": " + taskInfo.getTimeMillis() + " ms" +(isExceptionThrown ? " (thrown Exception)" : "");System.out.println(profileMessage);}}}
  1. 如您所见,我们的配置文件方法使用秒表来测量方法执行。
  2. 该方法从Spring-AOP接收ProceedingJoinPoint对象,该对象在执行该方法之前表示此情况下的方法执行关节点。该对象还有关于我们可以获得的要执行的方法的信息。
  3. 我们负责通过调用它的proceed()来执行该方法。
  4. 我们也知道在执行的日志记录方法中抛出的异常,但是我们将其推向透明,我们不希望在此级别处理异常,只记录它。

(“profile”方法签名受限于Spring AOP将调用它,但方法名称可以是将在spring.xml中设置的任何其他内容。)

Spring AOP配置XML

现在我们准备好了迷你应用程序中所需的每个工作类。让我们创建Spring的配置文件:

spring.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- Scans the classpath for annotated components that will be auto-registered as Spring beans --><context:component-scan base-package="hu.daniel.hari.learn.spring.aop.profiling" /><!-- Activates various annotations to be detected in bean classes e.g: @Autowired --><context:annotation-config /><!-- AOP Configuration for profiling --><!-- Our profiler class that we want to use to measure process time of service methods. --><bean id="profiler" class="hu.daniel.hari.learn.spring.aop.profiling.core.profiler.SimpleProfiler" /><!-- Spring AOP --><aop:config><aop:aspect ref="profiler"><!-- Catch all method in the service package through AOP. --><aop:pointcut id="serviceMethod" expression="execution(* hu.daniel.hari.learn.spring.aop.profiling.service.*.*(..))" /><!-- For these methods use the profile named method in the profiler class we defined below. --><aop:around pointcut-ref="serviceMethod" method="profile" /></aop:aspect></aop:config></beans>
  1. 首先我们告诉spring我们要对Spring组件使用类路径扫描(而不是在这个xml中逐个不方便地定义它们),并且我们还启用了Spring注释检测。
  2. 我们配置Spring-AOP,以捕获服务包中所有类的所有方法:
    1. 我们定义了一个“切入点”的方面 - 每个服务方法,
    2. 我们为这些切入点定义了一个“around”方法,该方法以SimpleProfiler的“profile”命名方法为目标。

Spring AOP方法分析测试类

而已!其余的只是我们应用程序的测试类。


package hu.daniel.hari.learn.spring.aop.profiling.main;import hu.daniel.hari.learn.spring.aop.profiling.service.FooService;import org.springframework.context.support.ClassPathXmlApplicationContext;/*** Example test class for Spring AOP Profiling.* * (remark: Exceptional calls should be put in try catch and handle ctx.close* properly but we missed to keep simleness of this example.)* * @author Daniel Hari*/
public class Main {public static void main(String[] args) {// Create Spring application context that configured by xml.ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/spring.xml");// Get our service from the spring context (that we want to be profiled).FooService fooService = ctx.getBean(FooService.class);// Test profiling through methods calls.for (int i = 0; i < 10; i++) {fooService.doShortJob();}fooService.doLongJob();// Test that profiler also can handle Exceptions in profiled method.fooService.doSomethingThatThrowsException();// Close the spring contextctx.close();}
}

您可以看到我们从main方法启动Spring容器并获取第一个依赖注入入口点(服务类实例)是多么简单。

如果你跑,你得到以下日志:


execution(FooService.doShortJob()): 38 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doShortJob()): 10 ms
execution(FooService.doLongJob()): 300 ms
execution(FooService.doSomethingThatThrowsException()): 0 ms (thrown Exception)
Exception in thread "main" java.lang.RuntimeException: Simulated Exception.at hu.daniel.hari.learn.spring.aop.profiling.service.FooService.doSomethingThatThrowsException(FooService.java:23)...

您可以看到为每个服务方法调用生成的分析日志。您可以在同一个包或更低版本中创建其他服务类,也可以对其进行分析。

如果您想了解AOP概念的工作原理,请查看以下参考链接。
如果您使用log4j.properties来自附加源的文件,并取消注释第一行,您可以看到幕后发生了什么。

参考文献:
使用Spring进行面向方面编程

您可以从下面的链接下载完整的maven项目源。

下载Spring AOP示例项目

Spring AOP方法分析相关推荐

  1. 史上最烂 spring aop 原理分析

    盗引·中篇·spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点.区别.使用方式.原理及各自对反射的优化.二者在 spring 中的统一.通知顺序.从 @Asp ...

  2. spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

    普通静态代理 代理类和真实类都需要实现同一个接口 接口 package com.fchan.layui.represent.service; /*** 静态代理demo*/ public interf ...

  3. spring getbean 方法分析

    spring 缺省: 1.spring用DefaultListableBeanFactory.preInstantiateSingletons()建立bean实例 2.缺省采用单例模式 在最近的项目中 ...

  4. Spring refresh 方法分析之一

    三哥 内容来自[自学星球] 欢迎大家来了解我的星球,和星主(也就是我)一起学习 Java ,深入 Java 体系中的所有技术.我给自己定的时间是一年,无论结果如何,必定能给星球中的各位带来点东西. 想 ...

  5. 一篇了解什么是Spring AOP

    AOP概述 AOP(Aspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善.它以通过预编译方式和运行期动态代理方 ...

  6. Spring事务原理分析(一)--@EnableTransactionManagement 到底做了什么?

    目录 一.概述 二.事务的ACID属性 三.事务的隔离级别 四.事务的传播行为 五.Spring声明式事务环境搭建 六.@EnableTransactionManagement分析 七.AutoPro ...

  7. spring AOP对父类方法加强分析

    spring AOP可以对方法进行加强,就是在方法前执行一些想要的事情,执行方法后想执行一些信息,原理就是利用动态代理,具体不在阐述 今天要讨论的是一个springBean继承了父类,在父类里进行了方 ...

  8. Spring AOP无法拦截内部方法调用-- expose-proxy=true用法

    假设一个接口里面有两个方法: package demo.long;public interface CustomerService { public void doSomething1(); publ ...

  9. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

最新文章

  1. zigzag扫描matlab,ZIGZAG扫描的MATLAB实现 | 学步园
  2. 白色flash模块代码_适用于MCU项目的代码框架BabyOS,工程师的好助手!
  3. 前端学习(1316):静态资源
  4. 决策树之 GBDT 算法 - 回归部分
  5. 设计一个方法输入字符串,字节数,输出截取的字符串
  6. 高效的JavaScript
  7. ulipad 常用快捷键
  8. 软考真题答案-2021年11月系统集成项目管理工程师下午题(一)
  9. python 屏幕代码雨效果(已验证)
  10. 【果壳笔记】生物信息学——陈润生老师部分
  11. 马尔科夫matlab程序,马尔科夫链matlab代码
  12. 计算机环境变量怎么恢复默认,环境变量怎么还原
  13. 全球及中国工业自动化电缆行业研究及十四五规划分析报告
  14. 云备份的正确打开方式,你学会了吗?
  15. git commit message——git提交日志规范备忘
  16. Uber是如何管理大规模数据工作流的?
  17. fastDB CLI
  18. 什么是 Workflow?
  19. 肯德基门店 csv
  20. HTML5期末大作业:影视网站设计——“指环王:护戒使者(13页) TML+CSS+JavaScript 学生DWHTML5网页设计成品_学生DW静态网页设计代做_web课程设计网页制作

热门文章

  1. 如何使用社会化媒体网络建立个人品牌(国外篇)
  2. Linux 技巧: Bash 测试和比较函数 (shell编程)
  3. 每个Linux用户都应该了解的命令行省时技巧
  4. 机器学习速成课程 | 练习 | Google Development——编程练习:逻辑回归
  5. 神奇的python(五)之python强制退出报错(异常)解决方法
  6. MongoDB基本概念和常用操作(一)
  7. Qt Ctreator搭配VS2013调试——整合QML/C++调试需要的从属调试引擎无法被创建
  8. 【AI视野·今日Robot 机器人论文速览 第十三期】Wed, 23 Jun 2021
  9. 【Linux入门学习之】Linux关机命令总结
  10. Collections工具类 java