鉴于以下类别:
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的配置阶段运行时,是否可以执行以下操作?
>捕获丢失的依赖项异常(或检测将会有一个)
>发现bean“foo”缺少的依赖“bar”是com.acme.Bar类型
>请注意,Bar是@AcmeService,因此我们将处理它.否则,错误可能被视为致命错误
>生成com.acme.Bar类型的代理
>将Bar代理注入Foo,确保可以使用Spring AOP建议Bar上的方法调用,就像我在Spring配置文件中明确创建了Bar代理并将代理注入Foo bean一样.
我最初被吸引到BeanPostProcessor和BeanFactoryPostProcessor作为实现这一点的手段,虽然在阅读文档后我没有看到一种明显的方式来做我想要的.
如果您想知道,我想要的基础用例是:
>将所有Spring上下文文件替换为我的服务层bean定义,并使用单个上下文文件生成@AcmeService bean接口的代理.
>建议对这些代理进行调用,而不是在服务层bean代理的接口模拟上调用. (踢球者是模拟在运行时由远程系统定义并上传到此应用程序以进行集成测试.对于我的常规单元测试,我做的更简单,只需根据需要创建和注入模拟).
除了整个“动态生成代理”位之外,我已经完成了所有这些工作.目前我在我的上下文文件中定义了我的服务接口的空实现,因此它们可以被注入和建议 – 但我宁愿没有生成和签入这么多空接口类.最后,我假设我需要生成这些代理,因为我不知道如何建议对null依赖项的尝试调用.
最佳答案 好的,这里有很多东西要讨论.
首先,我认为你不能完全按照你的要求去做.特别是,如果你有< property name =“bar”ref =“bar”/>并且bar没有bean定义,bean初始化将失败,我认为你不能轻易拦截它.当然,您可以编写自己的BeanFactory子类,但这不是一件容易接受的事情.
与您要求的最接近的现有机制是自动布线.看看AutowiredAnnotationBeanPostProcessor.您可以使用它作为编写自己的BeanPostProcessor的指南,它查看容器实例化的每个bean,查找属性,而这些属性又具有@AcmeService注释.当它找到一个时,它可以生成该类型的代理并注入它.
这将我们带到代理生成本身.寻找它的地方是ProxyFactory.这允许您在运行时生成实现任何接口或扩展任何类的对象,同时附加顾问程序/拦截器.这些拦截器可以完成所有工作 – 如果你不想,代理不必有任何“背后”的东西.
使用这种方法,您不需要“悬挂”< property name =“bar”ref =“bar”/>在您的配置中输入 – 在Foo中存在属性就足以触发该过程.