Advisor优化

master
linlei 2024-04-26 17:28:17 +08:00
parent c0c741e109
commit afb4410b1b
4 changed files with 45 additions and 45 deletions

View File

@ -7,8 +7,8 @@
- [四、接口源码](#四接口源码) - [四、接口源码](#四接口源码)
- [五、主要实现](#五主要实现) - [五、主要实现](#五主要实现)
- [六、最佳实践](#六最佳实践) - [六、最佳实践](#六最佳实践)
- [七、源码分析](#七源码分析) - [七、常见问题](#七常见问题)
- [八、常见问题](#八常见问题)
### 一、基本信息 ### 一、基本信息
@ -23,6 +23,7 @@
1. **组合切点和通知** 1. **组合切点和通知**
+ Advisor接口允许将切点Pointcut和通知Advice组合在一起。切点确定何时应该应用通知而通知定义了在连接点处执行的代码。 + Advisor接口允许将切点Pointcut和通知Advice组合在一起。切点确定何时应该应用通知而通知定义了在连接点处执行的代码。
3. **提供AOP配置的抽象** 3. **提供AOP配置的抽象**
+ Advisor接口是AOP配置的一种抽象它使得可以通过编程方式或声明式的方式定义切面并将它们应用到目标对象上。 + Advisor接口是AOP配置的一种抽象它使得可以通过编程方式或声明式的方式定义切面并将它们应用到目标对象上。
@ -97,7 +98,7 @@ public interface Advisor {
### 六、最佳实践 ### 六、最佳实践
使用Advisor来创建代理对象并应用切面逻辑。首先我们创建了一个代理工厂`ProxyFactory`,并将目标对象`MyService`传递给它。然后,我们通过`proxyFactory.addAdvisor(new MyCustomAdvisor())`添加了一个自定义的Advisor该Advisor定义了切点和通知。接着我们通过`proxyFactory.getProxy()`获取了代理对象`MyService`。最后,我们调用了代理对象的方法`proxy.foo()`和`proxy.bar()` 使用Advisor来创建代理对象并应用切面逻辑。首先通过创建代理工厂`ProxyFactory`,并将目标对象`MyService`传递给它。然后,通过`proxyFactory.addAdvisor(new MyCustomAdvisor())`添加了一个自定义的Advisor其中包含了切点和通知的定义。接着,通过`proxyFactory.getProxy()`获取了代理对象`MyService`。最后,调用了代理对象的`foo()`方法,该方法触发了切面逻辑的执行
```java ```java
public class AdvisorDemo { public class AdvisorDemo {
@ -110,19 +111,19 @@ public class AdvisorDemo {
// 获取代理对象 // 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy(); MyService proxy = (MyService) proxyFactory.getProxy();
// 调用方法 // 调用方法
proxy.foo(); // 会触发通知 proxy.foo();
proxy.bar(); // 不会触发通知
} }
} }
``` ```
`MyCustomAdvisor`类是一个自定义的Advisor继承自`AbstractPointcutAdvisor`用于将通知应用于带有特定注解的方法。在该类中,我们定义了一个通知对象`advice`和一个切点对象`pointcut`,切点用于匹配带有自定义注解`MyCustomAnnotation`的方法。通过实现`getPointcut()`方法和`getAdvice()`方法,我们指定了切点和通知的逻辑。这样在应用该Advisor时它将会根据定义的切点匹配带有指定注解的方法并在匹配的方法执行前后应用通知。 `MyCustomAdvisor`类是一个自定义的Advisor实现了`PointcutAdvisor`接口,并用于将通知应用于带有特定注解的方法。在该类中,我们定义了一个通知对象`advice`和一个切点对象`pointcut`,切点用于匹配带有自定义注解`MyCustomAnnotation`的方法。通过实现`getPointcut()`方法和`getAdvice()`方法,我们指定了切点和通知的逻辑。
```java ```java
/** /**
* 自定义Advisor用于将通知应用于带有特定注解的方法。 * 自定义Advisor用于将通知应用于带有特定注解的方法。
*/ */
public class MyCustomAdvisor extends AbstractPointcutAdvisor { public class MyCustomAdvisor implements PointcutAdvisor {
/** /**
* 通知对象 * 通知对象
@ -143,16 +144,28 @@ public class MyCustomAdvisor extends AbstractPointcutAdvisor {
public Advice getAdvice() { public Advice getAdvice() {
return advice; return advice;
} }
@Override
public boolean isPerInstance() {
return true;
}
} }
``` ```
`MyAdvice`类是一个通知类,实现了`MethodBeforeAdvice`接口,用于在目标方法执行前执行一些操作。 `MyAdvice`类是一个通知类,它实现了`MethodInterceptor`接口,用于在方法执行前后添加额外的逻辑。在`invoke`方法中,我们首先输出了正在调用的方法名,然后调用了`invocation.proceed()`方法来执行原始方法,并获取了方法执行的结果。最后,我们在方法执行之后再次输出了方法名
```java ```java
public class MyAdvice implements MethodBeforeAdvice { public class MyAdvice implements MethodInterceptor {
@Override @Override
public void before(Method method, Object[] args, Object target) throws Throwable { public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before method: " + method.getName()); // 在方法调用之前执行的逻辑
System.out.println("Before " + invocation.getMethod().getName());
// 调用原始方法
Object result = invocation.proceed();
// 在方法调用之后执行的逻辑
System.out.println("After " + invocation.getMethod().getName());
return result;
} }
} }
``` ```
@ -166,35 +179,27 @@ public @interface MyCustomAnnotation {
} }
``` ```
`MyService`类包含了两个方法`foo()`和`bar()`。其中,`foo()`方法被标记了`@MyCustomAnnotation`注解,而`bar()`方法没有。当调用`foo()`方法时,将会执行特定的逻辑,而调用`bar()`方法则不会执行特定逻辑。这种注解标记方式为方法提供了特殊的标记,使得在应用切面时可以针对带有特定注解的方法执行特定的通知 `MyCustomAnnotation`类其中包含一个名为`foo`的方法。该方法被`@MyCustomAnnotation`注解标记,表明需要特殊处理
```java ```java
public class MyService { public class MyService {
@MyCustomAnnotation @MyCustomAnnotation
public void foo() { public void foo() {
System.out.println("Executing foo method"); System.out.println("foo...");
}
public void bar() {
System.out.println("Executing bar method");
} }
} }
``` ```
运行结果,切面逻辑成功应用于带有特定注解的方法,并且未被标记的方法不受影响 运行结果,切面逻辑成功应用于带有特定注解的方法。
```java ```java
Before method: foo Before foo
Executing foo method foo...
Executing bar method After foo
``` ```
### 七、源码分析 ### 七、常见问题
暂无
### 八、常见问题
1. **切点定义错误** 1. **切点定义错误**

View File

@ -2,12 +2,6 @@ package com.xcs.spring;
import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.framework.ProxyFactory;
/**
* AdvisorDemo
*
* @author xcs
* @date
*/
public class AdvisorDemo { public class AdvisorDemo {
public static void main(String[] args) { public static void main(String[] args) {
@ -18,7 +12,6 @@ public class AdvisorDemo {
// 获取代理对象 // 获取代理对象
MyService proxy = (MyService) proxyFactory.getProxy(); MyService proxy = (MyService) proxyFactory.getProxy();
// 调用方法 // 调用方法
proxy.foo(); // 会触发通知 proxy.foo();
proxy.bar(); // 不会触发通知
} }
} }

View File

@ -1,12 +1,18 @@
package com.xcs.spring; package com.xcs.spring;
import org.springframework.aop.MethodBeforeAdvice; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method; public class MyAdvice implements MethodInterceptor {
public class MyAdvice implements MethodBeforeAdvice {
@Override @Override
public void before(Method method, Object[] args, Object target) throws Throwable { public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before method: " + method.getName()); // 在方法调用之前执行的逻辑
System.out.println("Before " + invocation.getMethod().getName());
// 调用原始方法
Object result = invocation.proceed();
// 在方法调用之后执行的逻辑
System.out.println("After " + invocation.getMethod().getName());
return result;
} }
} }

View File

@ -4,10 +4,6 @@ public class MyService {
@MyCustomAnnotation @MyCustomAnnotation
public void foo() { public void foo() {
System.out.println("Executing foo method"); System.out.println("foo...");
}
public void bar() {
System.out.println("Executing bar method");
} }
} }