跳到主要内容
版本:7.0.3

操作建议对象

Hunyuan 7b 中英对照 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();

getAdvisors() 方法会为工厂中添加的每个顾问(Advisor)、拦截器(Interceptor)或其他类型的建议(Advice)返回一个对应的顾问对象。如果你添加的是一个顾问,那么在该索引位置返回的顾问对象就是你所添加的那个对象;而如果你添加的是拦截器或其他类型的建议,Spring 会将其包装在一个顾问对象中,该顾问对象的切点(Pointcut)总是返回 true。因此,如果你添加的是一个 MethodInterceptor,那么在该索引位置返回的顾问对象实际上是一个 DefaultPointcutAdvisor,它既包含你添加的 MethodInterceptor,还包含一个能够匹配所有类和方法的切点。

addAdvisor() 方法可以用来添加任何类型的 Advisor。通常,持有切点和建议(advice)的顾问(advisor)是通用的 DefaultPointcutAdvisor,你可以将其与任何建议或切点(pointcut)一起使用(但不适用于引入(introductions)操作)。

默认情况下,即使在代理创建之后,也可以添加或删除顾问(advisors)或拦截器(interceptors)。唯一的限制是无法添加或删除引入顾问(introduction advisor),因为工厂(factory)中现有的代理不会显示接口的变更。(你可以从工厂获取一个新的代理来避免这个问题。)

以下示例展示了将AOP代理强制转换为Advised接口,并检查及操作其通知(advice):

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

在生产环境中修改对业务对象的“建议”(此处无双关意味)是否明智,这是值得商榷的,尽管无疑存在一些合理的使用场景。然而,在开发过程中(例如在测试中),这样做可能会非常有用。我们有时发现,能够以拦截器或其他“建议”的形式添加测试代码是非常有用的,这样就可以进入我们想要测试的方法调用过程。(例如,该“建议”可以进入为该方法创建的事务中,或许可以运行SQL语句来检查数据库是否被正确更新,然后再标记该事务进行回滚。)

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