可定制的@Autowired

时间:2011-12-14 21:22:46

标签: java spring inversion-of-control autowired

假设我有一个带注释的bean属性设置器,如下所示:

public class Foo {
  ...
  @Autowired 
  public void setBar(Bar bar) {
    ...
}

Springframework将像往常一样查找匹配的Bar属性。但是,我想拦截默认的bean解析过程并自己添加一些“魔法”。我想介绍一个像这样的解析器:

public interface SomeResolverInterface<T> {
  public T resolve(Class<T> beanClass);
}

public class BarResolver implements SomeResolverInterface<Bar> {

  @Override
  public Bar resolve(Class<Bar> beanClass) {
    if(someCondition) {
      return someBean;
    } else {
      return anotherBean;
    }
  }

  ...

我知道我总是可以引入某种包装bean并将解析逻辑移到这里但是我更喜欢使用如上所述的解析器更通用的方式使Foo完全独立于解析逻辑。

Springframework中是否有办法实现这样的目标?

3 个答案:

答案 0 :(得分:4)

从您的描述中看起来您只需要在启动时执行其他逻辑(自动装配)。有几种方法可以解决这个问题(从最差到最好):

  • AOP - 糟糕的主意,通过拦截每次调用来引入运行时开销

  • 自定义范围 - 请参阅:Custom spring scopes?也适用于运行时,也是一个坏主意

  • @Profile - 定义两个匹配的bean,并且只根据活动的配置文件启用一个。非常干净,仅在启动时引入开销

  • @Configuration - 在Java中定义bean具有完全控制它们如何创建的额外好处:


@Configuration
public class Config {

    @Autowired
    private Bar someBean;

    @Autowired
    private Bar anotherBean;

    @Bean
    @Primary
    public Bar primaryBean() {
        if(someCondition) {
          return someBean;
        } else {
          return anotherBean;
        }
      }

}

正如您在本案中所看到的,我们有三个Bar类型的bean:someBeananotherBeanprimaryBean。前两个也可以使用@Bean或使用@Service进行组件扫描进行配置。但要使自动装配成为可能,最后primaryBean标记为@Primary。这种方式比其他两种方式更受欢迎。

这是我推荐的解决方案,因为解析逻辑是干净,可维护和可读的。恕我直言,这是基于Java的@Configuration真正发光的情况。

答案 1 :(得分:2)

除了Tomasz提供的@Configuration选项外,您还可以使用简单的FactoryBean。只需实现接口,并声明工厂bean。在getObject()方法中执行自定义逻辑。

答案 2 :(得分:0)

虽然我从未尝试过这个,但我认为你可以通过

来看待你的逻辑
AnnotationConfigUtils

或者看看

AutowiredAnnotationBeanPostProcessor

并查看它是否允许简单扩展/插入逻辑