|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
操控被增强的对象
无论您如何创建AOP代理,都可以通过使用org.springframework.aop.framework.Advised接口来操作它们。任何AOP代理都可以转换为此接口,无论它实现了哪些其他接口。此接口包含以下方法:
-
Java
-
Kotlin
Advisor[] getAdvisors();
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
int indexOf(Advisor advisor);
boolean removeAdvisor(Advisor advisor) throws AopConfigException;
void removeAdvisor(int index) throws AopConfigException;
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
boolean isFrozen();
fun getAdvisors(): Array<Advisor>
@Throws(AopConfigException::class)
fun addAdvice(advice: Advice)
@Throws(AopConfigException::class)
fun addAdvice(pos: Int, advice: Advice)
@Throws(AopConfigException::class)
fun addAdvisor(advisor: Advisor)
@Throws(AopConfigException::class)
fun addAdvisor(pos: Int, advisor: Advisor)
fun indexOf(advisor: Advisor): Int
@Throws(AopConfigException::class)
fun removeAdvisor(advisor: Advisor): Boolean
@Throws(AopConfigException::class)
fun removeAdvisor(index: Int)
@Throws(AopConfigException::class)
fun replaceAdvisor(a: Advisor, b: Advisor): Boolean
fun isFrozen(): Boolean
The getAdvisors() 方法返回一个 Advisor,对于添加到工厂中的每个顾问、拦截器或其他建议类型。如果你添加了一个 Advisor,则返回的顾问在这个索引处是你添加的对象。如果你添加了拦截器或其他建议类型,Spring 将其包装在一个具有始终返回 true 的切入点的顾问中。因此,如果你添加了一个 MethodInterceptor,则返回的顾问是返回你的 MethodInterceptor 和匹配所有类和方法的切入点的 DefaultPointcutAdvisor。
The addAdvisor() 方法可以用于添加任何 Advisor。通常,持有切点和通知的顾问是通用的 DefaultPointcutAdvisor,你可以将其与任何通知或切点一起使用(但不适用于引介)。
默认情况下,即使在创建代理之后,也可以添加或删除顾问或拦截器。唯一的限制是无法添加或删除引入顾问,因为工厂现有的代理不会显示接口更改。(你可以从工厂获取一个新的代理来避免这个问题。)
以下示例展示了将AOP代理转换为Advised接口并检查和操作其通知:
-
Java
-
Kotlin
Advised advised = (Advised) myObject;
Advisor[] advisors = advised.getAdvisors();
int oldAdvisorCount = advisors.length;
System.out.println(oldAdvisorCount + " advisors");
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(new DebugInterceptor());
// Add selective advice using a pointcut
advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
val advised = myObject as Advised
val advisors = advised.advisors
val oldAdvisorCount = advisors.size
println("$oldAdvisorCount advisors")
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(DebugInterceptor())
// Add selective advice using a pointcut
advised.addAdvisor(DefaultPointcutAdvisor(mySpecialPointcut, myAdvice))
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.advisors.size)
| 修改业务对象上的通知是否明智值得商榷(无意双关),尽管毫无疑问存在合理的使用场景。然而,在开发中(例如在测试中)这可能非常有用。我们有时发现,能够以拦截器或其他通知的形式添加测试代码非常有用,这样可以深入到我们想要测试的方法调用中。例如,通知可以进入为该方法创建的事务中,也许是为了运行SQL来检查数据库是否正确更新,然后再标记事务回滚。 |
取决于您创建代理的方式,通常可以设置一个frozen标志。在这种情况下,Advised isFrozen()方法返回true,并且任何通过添加或删除来修改建议的尝试都会导致AopConfigException。在某些情况下(例如,为了防止调用代码移除安全拦截器),冻结被建议对象的状态的能力是有用的。