Advice优化

master
linlei 2024-04-28 14:08:40 +08:00
parent 706dddd31a
commit ec50207522
19 changed files with 94 additions and 90 deletions

View File

@ -15,7 +15,7 @@
### 二、基本描述
`AfterReturningAdvice`接口是Spring AOP框架中的一个核心接口用于在目标方法执行后拦截并执行自定义逻辑。通过实现该接口的`afterReturning`方法,可以在目标方法成功返回结果后进行一些操作,如日志记录、性能监控等
`AfterReturningAdvice`接口是Spring AOP框架中的一个核心接口用于在目标方法执行后拦截并执行自定义逻辑。通过实现该接口的`afterReturning`方法,可以在目标方法成功返回结果后进行一些操作。
### 三、主要功能
@ -24,9 +24,8 @@
+ 记录目标方法的执行情况,如方法名称、参数值、返回结果等,以便跟踪应用程序的运行状态。
2. **性能监控**
+ 统计目标方法的执行时间,分析应用程序的性能瓶颈,优化程序性能。
3. **缓存处理**
+ 在方法返回结果后,将结果缓存起来,以提高后续相同请求的响应速度。
@ -83,7 +82,7 @@ public class AfterReturningAdviceDemo {
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}
```
@ -94,28 +93,27 @@ public class AfterReturningAdviceDemo {
public class MyAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("After method " + method.getName() + " is called, returned value: " + returnValue);
System.out.println("After Method " + method.getName());
}
}
```
`MyService` 类是一个简单的服务类,其中包含了一个名为 `doSomething()` 的方法。在上下文中,`MyService` 类被用作目标对象,即需要被拦截和增强的对象。
`MyService` 类是一个简单的服务类,其中包含了一个名为 `foo()` 的方法。在上下文中,`MyService` 类被用作目标对象,即需要被拦截和增强的对象。
```java
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
}
}
```
运行结果,成功地执行了代理对象的`doSomething()`方法,并在方法执行完成后,后置返回通知`MyAfterReturningAdvice`被触发。
运行结果,成功地执行了代理对象的`foo()`方法,并在方法执行完成后,后置返回通知`MyAfterReturningAdvice`被触发。
```java
Doing something...
After method doSomething is called, returned value: hello world
foo...
After Method foo
```
### 七、常见问题

View File

@ -12,6 +12,6 @@ public class AfterReturningAdviceDemo {
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}

View File

@ -7,6 +7,6 @@ import java.lang.reflect.Method;
public class MyAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("After method " + method.getName() + " is called, returned value: " + returnValue);
System.out.println("After Method " + method.getName());
}
}

View File

@ -2,8 +2,7 @@ package com.xcs.spring;
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
}
}

View File

@ -1,14 +1,13 @@
## IntroductionInterceptor
- [IntroductionInterceptor](#IntroductionInterceptor)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
- [三、主要功能](#三主要功能)
- [四、接口源码](#四接口源码)
- [五、主要实现](#五主要实现)
- [六、最佳实践](#六最佳实践)
- [七、源码分析](#七源码分析)
- [八、常见问题](#八常见问题)
- [IntroductionInterceptor](#introductioninterceptor)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
- [三、主要功能](#三主要功能)
- [四、接口源码](#四接口源码)
- [五、主要实现](#五主要实现)
- [六、最佳实践](#六最佳实践)
- [七、常见问题](#七常见问题)
### 一、基本信息
@ -69,11 +68,11 @@ public class IntroductionInterceptorDemo {
// 创建代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
// 开始监控
((MyMonitoringCapable) proxy).toggleMonitoring();
// 再次调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}
```
@ -98,12 +97,11 @@ public class MyMonitoringIntroductionAdvice extends DelegatingIntroductionInterc
@Override
protected Object doProceed(MethodInvocation mi) throws Throwable {
if (this.active) {
System.out.println("开启监控...");
System.out.println("[开启监控" + mi.getMethod().getName() + "]");
long startTime = System.currentTimeMillis();
Object result = super.doProceed(mi);
long endTime = System.currentTimeMillis();
System.out.println(mi.getClass().getName() + "." + mi.getMethod().getName() + " 耗费时间:" + (endTime - startTime) + " 毫秒");
System.out.println("结束监控...");
System.out.println("[结束监控" + mi.getMethod().getName() + "] 耗费时间:" + (endTime - startTime) + " 毫秒");
return result;
}
return super.doProceed(mi);
@ -119,24 +117,36 @@ public interface MyMonitoringCapable {
}
```
`MyService` 类是一个简单的服务类,其中包含了一个名为 `doSomething()` 的方法。在上下文中,`MyService` 类被用作目标对象,即需要被拦截和增强的对象。
`MyService` 类是一个简单的服务类,其中包含了一个名为 `foo()` 的方法。在上下文中,`MyService` 类被用作目标对象,即需要被拦截和增强的对象。
```java
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
```
运行结果,这个运行结果说明了引介通知成功地增强了目标方法,实现了在目标方法执行前后动态地添加额外的逻辑。
```java
foo...
[开启监控foo]
foo...
[结束监控foo] 耗费时间1008 毫秒
```
### 七、常见问题
1. **引介的作用和优势是什么?**
- 这个问题探讨了引介在 AOP 中的作用和优势,以及它与其他 AOP 概念(如通知、切点)的区别。
2. **如何实现引介?**
- 这个问题涉及到如何使用 `IntroductionInterceptor` 接口以及其子类来实现引介功能,以及在 Spring AOP 中如何配置和应用引介。

View File

@ -15,10 +15,10 @@ public class IntroductionInterceptorDemo {
// 创建代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
// 开始监控
((MyMonitoringCapable) proxy).toggleMonitoring();
// 再次调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}

View File

@ -20,12 +20,11 @@ public class MyMonitoringIntroductionAdvice extends DelegatingIntroductionInterc
@Override
protected Object doProceed(MethodInvocation mi) throws Throwable {
if (this.active) {
System.out.println("开启监控...");
System.out.println("[开启监控" + mi.getMethod().getName() + "]");
long startTime = System.currentTimeMillis();
Object result = super.doProceed(mi);
long endTime = System.currentTimeMillis();
System.out.println(mi.getClass().getName() + "." + mi.getMethod().getName() + " 耗费时间:" + (endTime - startTime) + " 毫秒");
System.out.println("结束监控...");
System.out.println("[结束监控" + mi.getMethod().getName() + "] 耗费时间:" + (endTime - startTime) + " 毫秒");
return result;
}
return super.doProceed(mi);

View File

@ -2,8 +2,12 @@ package com.xcs.spring;
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -93,7 +93,7 @@ public class MethodBeforeAdviceDemo {
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("Before method " + method.getName() + " is called.");
System.out.println("Before method " + method.getName());
}
}
```
@ -103,18 +103,17 @@ public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
```java
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
}
}
```
运行结果,调用目标方法`doSomething`之前,`MyMethodBeforeAdvice`中的前置通知被成功触发,并打印了相应的信息。
运行结果,调用目标方法`foo`之前,`MyMethodBeforeAdvice`中的前置通知被成功触发,并打印了相应的信息。
```java
Before method doSomething is called.
Doing something...
Before method foo
foo...
```
### 七、常见问题

View File

@ -12,6 +12,6 @@ public class MethodBeforeAdviceDemo {
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}

View File

@ -7,6 +7,6 @@ import java.lang.reflect.Method;
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("Before method " + method.getName() + " is called.");
System.out.println("Before method " + method.getName());
}
}

View File

@ -2,8 +2,7 @@ package com.xcs.spring;
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
}
}

View File

@ -8,8 +8,6 @@
- [六、最佳实践](#六最佳实践)
- [七、常见问题](#七常见问题)
### 一、基本信息
✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https://github.com/xuchengsheng/spring-reading)
@ -85,45 +83,45 @@ public class MethodInterceptorDemo {
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}
```
`MyMethodInterceptor` 类用于实现方法拦截和增强的功能。在 `invoke()` 方法中,首先通过 `MethodInvocation` 对象获取被调用方法的信息,例如方法名等,并在方法调用之前输出方法被调用的信息。然后调用 `invocation.proceed()` 方法来执行原始方法,获取方法执行结果。最后,在方法调用之后输出方法返回值,并将其返回。
`MyMethodInterceptor` 类用于实现方法拦截和增强的功能。在 `invoke()` 方法中,首先通过 `MethodInvocation` 对象获取被调用方法的信息,例如方法名等,并在方法调用之前输出方法被调用的信息。然后调用 `invocation.proceed()` 方法来执行原始方法,获取方法执行结果。最后并将其返回。
```java
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 在方法调用之前执行的逻辑
System.out.println("Method " + invocation.getMethod().getName() + " is called.");
System.out.println("Before Method " + invocation.getMethod().getName());
// 调用原始方法
Object result = invocation.proceed();
// 在方法调用之后执行的逻辑
System.out.println("Method " + invocation.getMethod().getName() + " returns " + result);
System.out.println("After Method " + invocation.getMethod().getName());
return result;
}
}
```
`MyService` 类是一个简单的服务类,其中包含了一个名为 `doSomething()` 的方法。在上下文中,`MyService` 类被用作目标对象,即需要被拦截和增强的对象。
`MyService` 类是一个简单的服务类,其中包含了一个名为 `foo()` 的方法。在上下文中,`MyService` 类被用作目标对象,即需要被拦截和增强的对象。
```java
public class MyService {
public void doSomething() {
System.out.println("Doing something...");
public void foo() {
System.out.println("foo...");
}
}
```
运行结果,在调用 `MyService` 实例的 `doSomething()` 方法时,`MyMethodInterceptor` 拦截器成功地拦截了方法的执行,并在方法执行前后添加了额外的逻辑处理。
运行结果,在调用 `MyService` 实例的 `foo()` 方法时,`MyMethodInterceptor` 拦截器成功地拦截了方法的执行,并在方法执行前后添加了额外的逻辑处理。
```java
Method doSomething is called.
Doing something...
Method doSomething returns hello world
Before Method foo
foo...
After Method foo
```
### 七、常见问题

View File

@ -1,8 +1,6 @@
package com.xcs.spring;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class MethodInterceptorDemo {
@ -10,10 +8,10 @@ public class MethodInterceptorDemo {
// 创建代理工厂&创建目标对象
ProxyFactory proxyFactory = new ProxyFactory(new MyService());
// 创建通知
proxyFactory.addAdvisor(new DefaultPointcutAdvisor(Pointcut.TRUE, new MyMethodInterceptor()));
proxyFactory.addAdvice(new MyMethodInterceptor());
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomething();
proxy.foo();
}
}

View File

@ -7,11 +7,11 @@ public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 在方法调用之前执行的逻辑
System.out.println("Method " + invocation.getMethod().getName() + " is called.");
System.out.println("Before Method " + invocation.getMethod().getName());
// 调用原始方法
Object result = invocation.proceed();
// 在方法调用之后执行的逻辑
System.out.println("Method " + invocation.getMethod().getName() + " returns " + result);
System.out.println("After Method " + invocation.getMethod().getName());
return result;
}
}

View File

@ -2,8 +2,7 @@ package com.xcs.spring;
public class MyService {
public String doSomething() {
System.out.println("Doing something...");
return "hello world";
public void foo() {
System.out.println("foo...");
}
}

View File

@ -16,7 +16,7 @@
### 二、基本描述
`ThrowsAdvice`接口是Spring AOP中的一种通知类型用于在方法抛出异常时执行额外的逻辑。实现该接口的类可以捕获方法抛出的异常并执行自定义的异常处理逻辑,比如记录日志、发送通知等
`ThrowsAdvice`接口是Spring AOP中的一种通知类型用于在方法抛出异常时执行额外的逻辑。实现该接口的类可以捕获方法抛出的异常并执行自定义的异常处理逻辑。
### 三、主要功能
@ -74,11 +74,12 @@ public interface ThrowsAdvice extends AfterAdvice {
### 五、主要实现
暂无
1. **ThrowsAdviceInterceptor**
+ 用于拦截方法抛出的异常,并触发相应的异常通知(`ThrowsAdvice`)。它负责捕获方法执行过程中抛出的异常,并调用相关的异常通知来处理异常情况。
### 六、最佳实践
使用`ThrowsAdvice`接口来处理方法抛出的异常。它创建了一个代理工厂,并将目标对象(`MyService`)和异常通知(`MyThrowsAdvice`)传递给代理工厂。然后,它通过代理工厂获取代理对象,并调用代理对象的方法`doSomethingException()`。
使用`ThrowsAdvice`接口来处理方法抛出的异常。它创建了一个代理工厂,并将目标对象(`MyService`)和异常通知(`MyThrowsAdvice`)传递给代理工厂。然后,它通过代理工厂获取代理对象,并调用代理对象的方法`foo()`。
```java
public class ThrowsAdviceDemo {
@ -91,7 +92,7 @@ public class ThrowsAdviceDemo {
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomethingException();
proxy.foo();
}
}
```
@ -106,19 +107,19 @@ public class MyThrowsAdvice implements ThrowsAdvice {
}
```
`MyService`类包含了一个名为`doSomethingException()`的方法,该方法执行某些操作,并故意引发了一个异常(通过除以零)。
`MyService`类包含了一个名为`foo()`的方法,该方法执行某些操作,并故意引发了一个异常(通过除以零)。
```java
public class MyService {
public void doSomethingException() {
System.out.println("Doing something exception...");
public void foo() {
System.out.println("foo...");
int i = 1 / 0;
}
}
```
运行结果,当调用了`MyService`类的`doSomethingException()`方法,但在该方法中发生了除以零的错误,导致了`java.lang.ArithmeticException: / by zero`异常的抛出。
运行结果,当调用了`MyService`类的`foo()`方法,但在该方法中发生了除以零的错误,导致了`java.lang.ArithmeticException: / by zero`异常的抛出。
```java
Doing something exception...

View File

@ -2,8 +2,8 @@ package com.xcs.spring;
public class MyService {
public void doSomethingException() {
System.out.println("Doing something exception...");
public void foo() {
System.out.println("foo...");
int i = 1 / 0;
}
}

View File

@ -12,6 +12,6 @@ public class ThrowsAdviceDemo {
// 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy();
// 调用代理对象的方法
proxy.doSomethingException();
proxy.foo();
}
}