跳到主要内容

操作建议对象

ChatGPT-4o-mini 中英对照 Manipulating Advised Objects

然而,无论你如何创建 AOP 代理,你都可以通过使用 org.springframework.aop.framework.Advised 接口来操作它们。任何 AOP 代理都可以被转换为这个接口,无论它实现了哪些其他接口。这个接口包括以下方法:

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

getAdvisors() 方法返回每个已添加到工厂的顾问、拦截器或其他建议类型的 Advisor。如果您添加了一个 Advisor,则在此索引处返回的顾问是您添加的对象。如果您添加了一个拦截器或其他建议类型,Spring 会将其包装在一个总是返回 true 的切入点顾问中。因此,如果您添加了一个 MethodInterceptor,则在此索引处返回的顾问是一个 DefaultPointcutAdvisor,它返回您的 MethodInterceptor 以及一个匹配所有类和方法的切入点。

addAdvisor() 方法可以用来添加任何 Advisor。通常,持有切入点和通知的顾问是通用的 DefaultPointcutAdvisor,您可以将其与任何通知或切入点一起使用(但不能用于引介)。

默认情况下,即使在创建代理之后,也可以添加或移除顾问或拦截器。唯一的限制是无法添加或移除引介顾问,因为来自工厂的现有代理不会显示接口的变化。(您可以从工厂获取一个新的代理以避免此问题。)

以下示例展示了将 AOP 代理转换为 Advised 接口,并检查和操作其建议:

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);
java
备注

是否建议在生产环境中修改业务对象的建议是值得怀疑的(并无双关之意),尽管毫无疑问,确实存在合理的使用案例。然而,在开发中这可能非常有用(例如,在测试中)。我们有时发现能够以拦截器或其他建议的形式添加测试代码非常有用,从而进入我们想要测试的方法调用内部。(例如,建议可以进入为该方法创建的事务,也许在标记事务回滚之前运行 SQL 来检查数据库是否正确更新。)

根据您创建代理的方式,通常可以设置一个 frozen 标志。在这种情况下,AdvisedisFrozen() 方法返回 true,任何通过添加或删除来修改建议的尝试都会导致 AopConfigException。在某些情况下,冻结被建议对象的状态是有用的(例如,防止调用代码移除安全拦截器)。