如何自动创建并注入缺失依赖项的代理?

4

以下是给定的类:

package com.acme;

public class Foo {
  private Bar bar;
  public void setBar(Bar newBar) {
    this.bar = newBar;
  }
}

@AcmeService
public interface Bar {}

并且一个Spring配置文件如下:

<beans>
  <bean id="foo" class="com.acme.Foo">
    <property name="bar" ref="bar" />
  </bean>
</beans>

当Spring的配置阶段运行时,是否可以执行以下操作?
  1. 捕获缺少依赖项异常(或检测到将要发生的异常)
  2. 发现bean“foo”的缺少依赖项“bar”是类型为com.acme.Bar
  3. 注意Bar是@AcmeService,因此我们将处理它。否则,错误可以被视为致命错误
  4. 生成类型为com.acme.Bar的代理
  5. 将Bar代理注入Foo,确保可以像在Spring配置文件中显式创建Bar代理并将代理注入Foo bean一样使用Spring AOP对Bar上的方法调用进行通知。
我最初想到了BeanPostProcessor和BeanFactoryPostProcessor作为实现这一点的手段,尽管在阅读文档后,我没有看到明显的方法来做到我想要的。
如果你想知道的话,底层用例是我想:
  • 用单个上下文文件替换所有带有服务层bean定义的Spring上下文文件,并生成@AcmeService bean接口的代理。
  • 通知针对这些代理的调用改为在服务层bean代理的接口模拟上调用。(问题在于模拟是由远程系统在运行时定义的,并上传到此应用程序以进行集成测试。对于我的常规单元测试,我会像需要的那样创建和注入模拟)。
我已经将所有这些都实现了,除了动态生成代理的部分。目前,在我的上下文文件中定义了我的服务接口的空实现,以便可以注入和通知它们-但我不想有那么多空接口类生成和检入。最后,我假设我需要生成这些代理,因为我不知道如何通知对空依赖项的尝试调用。
1个回答

2

好的,这里有很多需要讨论的事情。

首先,我不认为您能够完全实现您所要求的。特别是,如果您有<property name="bar" ref="bar"/>,但没有bar的bean定义,则bean初始化将失败,并且我不认为您可以轻易地拦截它。当然,您可以编写自己的BeanFactory子类,但这不是轻松的事情。

最接近您所要求的现有机制是自动装配。请查看AutowiredAnnotationBeanPostProcessor。您可以使用此作为编写自己的BeanPostProcessor的指南,该处理器在容器实例化每个bean时查看属性,查找那些类型的属性,这些类型又具有@AcmeService注释。找到后,它可以生成该类型的代理并注入它。

这就带我们进入了代理生成本身。要查找的位置是ProxyFactory。这使您可以在运行时生成实现任何接口或扩展任何类的对象,同时附加advisors/interceptors。这些拦截器可以完成所有工作-如果您不想要任何“后面”的代理,则代理不必有任何内容。

使用此方法,您将不需要在配置中使用“悬挂”的<property name="bar" ref="bar"/>条目-在Foo中存在该属性就足以触发该进程。


1
感谢您的帮助!乍一看,子类化AutowiredAnnotationBeanPostProcessor并提供自定义实现的findAutowireCandidates可能已经足够接近我所需的内容了。我会进一步调查,如果证明有效,我会接受您的答案! - Brian Laframboise
1
结果表明,我想要的事情真的是不可能的,但幸运的是,对我的问题采用了不同的方法,反正也不需要这样做。 - Brian Laframboise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接