Spring 框架入门教程
1. 1. Spring 框架 2. 2. Spring 5 3. 3. Spring WebFlux 4. 4. 先介绍一下 Spring 5. 5. 什么是 Spring 依赖注入 6. 6. 什么是 Spring IoC 容器 和 Bean 7. 7. Spring Bean 的生命周期 8. 8. Spring REST 开发 9. 9. Spring REST XML 10. 10. Spring RestTemplate 开发 11. 11. Spring AOP 切面编程 12. 12. Spring AOP 方法调优 13. 13. Spring 注解详解 14. 14. Spring 核心注解之 @Autowired 15. 15. Spring 核心注解之 @RequestMapping 16. 16. Spring MVC 开发样例 17. 17. Spring MVC 开发指南 18. 18. Spring MVC 异常处理机制 19. 19. Spring MVC Validator 20. 20. Spring MVC 拦截器 21. 21. Spring MVC 文件上传 22. 22. Spring MVC 国际化(i18n) 23. 23. Spring MVC Hibernate MqSQL 24. 24. Spring ORM 25. 25. Spring ORM JPA 26. 26. Spring Data JPA 27. 27. Spring 事务管理 28. 28. 常用的 Spring JdbcTemplate 29. 29. Spring Security 简介 30. 30. Spring Security 教程 31. 31. Spring Security UserDetailsService 32. 32. Spring MVC 登录注销简单案例 33. 33. Spring Security Roles 34. 34. Spring Boot Tutorial 35. 35. Spring Boot Components 36. 36. Spring Boot CLI Hello World 37. 37. Spring Boot Initilizr Web 38. 38. Spring Boot Initilizr IDE 39. 39. Spring Boot Initilizr CLI 40. 40. Spring Boot Initilizr Tools 41. 41. Spring Boot MongoDB 42. 42. Spring Boot Redis Cache 43. 43. Spring Boot 常见面试问题 44. 44. Spring Batch 45. 45. Spring Batch 批处理示例 46. 46. Spring AMQP 47. 47. Spring RabbitMQ 48. 48. Spring AMQP RabbitMQ 49. 49. Apache ActiveMQ 安装与启动 50. 50. Spring ActiveMQ 教程 51. 51. Spring ActiveMQ 示例 52. 52. Spring JDBC 53. 53. Spring DataSource JNDI 54. 54. Spring Hibernate 55. 55. Spring Primefaces JPA 56. 56. Spring Primefaces MongoDB 57. 57. Spring Primefaces Hibernate 58. 58. SpringRoo Primefaces Hibernate 59. 59. Spring JSF 60. 60. Spring JDF Hibernate 61. 61. Spring Data MongoDB 62. 62. Spring 常见面试问题

12. Spring AOP 方法调优

这个例子展示了如何配置Spring Aop方法评测。我们可以利用面向切面编程使用任何服务(或其他)类中的任何方法,而不在任何服务类中编写一行分析代码。面向切面编程(AOP)允许我们从服务代码中分离(通常是重复的和样板的)分析代码。

Spring AOP方法剖析

我们只在单独的类中编写一次探查器代码(SimpleProfiler.java),仅此而已,其余的只是spring.xml that has to be done for working.

所以我们可以对下面的内容进行方法分析。

  1. 分析任何(服务)类,
  2. 不接触(服务)课程和代码,
  3. 通过Spring Aop方法。

Spring Aop方法剖析项目结构

Spring Aop-Maven依赖项

我们将首先调查pom.xml文件所有必需的依赖项及其版本的文件。我们在这个例子中使用的是spring4。


<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://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背景作为Spring依赖项。
  • Springaop还附带了spring context作为它的依赖库,因此不需要添加它。
  • aspectjweaver公司是Spring Aop的依赖项,但是我们必须添加它,因为它没有为Spring Aop明确定义。

Spring服务类(待分析)

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


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();
		}
	}
}

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

SpringAOP探查器类

我们的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 method
			return proceedingJoinPoint.proceed();
		} catch (RuntimeException e) {
			isExceptionThrown = true;
			throw e;
		} finally {
			stopWatch.stop();
			TaskInfo taskInfo = stopWatch.getLastTaskInfo();
			// Log the method"s profiling result
			String profileMessage = taskInfo.getTaskName() + ": " + taskInfo.getTimeMillis() + " ms" +
					(isExceptionThrown ? " (thrown Exception)" : "");
			System.out.println(profileMessage);
		}
	}
	
}
  1. 如您所见,我们的profile方法使用秒表来测量方法执行情况。
  2. 该方法从Spring Aop接收ProceedingJoinPoint对象,该对象表示在执行方法之前的方法执行连接点。这个对象还有关于要执行的方法的信息,我们可以得到。
  3. 我们负责通过调用该方法&8217;s proceed()来执行该方法。
  4. 我们确实知道异常也在执行的方法中抛出,以便记录它,但是我们将它向前抛出是为了透明,我们不想在这个级别处理异常,只想记录它。

(“;profile”;方法签名是有界的,因为Spring AOP将调用它,但是方法名可以是任何其他将在中设置的spring.xml文件.)

Spring Aop配置XML

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

spring.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans" xmlns:context="https://www.springframework.org/schema/context" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		https://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		https://www.springframework.org/schema/context
		https://www.springframework.org/schema/context/spring-context-4.0.xsd
		https://www.springframework.org/schema/aop
        https://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" />

	<!-- 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. 我们定义了一个方面,它“;切入点”;-s每个服务方法,
    2. 我们为这些切入点定义了一个“;around”;方法,该方法的目标是我们的SimpleProfiler’;s“;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 context
		ctx.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 file from attached source, and uncomment first line(s) you can see what’s going on under the hood.

参考文献:

精选推荐