7

IoC 很好,但是与自动装配一起使用(@EJB、@Autowired、@Inject、@SpringBean...),你不认为它限制了 IoC 的目标吗?

实际上我对不同框架中的自动装配系统了解不多,但似乎它主要基于类型。

当您在 IService 上使用 @EJB 时,您只需要一个实现 ServiceImpl 即可使其工作。

如果我们想要很多实现怎么办?

似乎一些自动装配注释可以有参数。例如在 Stripes 中你可以这样做: @SpringBean("xxxService") 其中 xxxService 是一个 spring 初始化的 bean。

在这种情况下,好吧,你不要执行“new XxxServiceImpl()”,但你仍然对你想在你的 bean 中使用的服务实现进行硬编码引用。它根本不是类引用,而是对实现的 spring bean 引用......

你怎么看?我喜欢自动装配,但只是想知道自己....

4

4 回答 4

6

是的,自动装配有一些限制(只有一个自动装配接口的实现),因此在注入正确的实现时它破坏了 IoC 灵活性的一部分。

但是,我认为自动装配只是一种减少配置的方法。因此,当 90% 的依赖项可以自动装配时,您最终的总体配置往往会减少(剩余的配置很重要,因为它只包含重要的(特定于实现的)位)

于 2010-12-17T14:06:40.927 回答
2

我怀疑这可以被认为是一个客观的问题,但让我们试一试。

我对此进行了相当多的讨论,当然不仅仅是你这样想。

是的,这样做会让 IoC 变得毫无意义。它仍然更容易,因为您不必自己找出理想的接线顺序,但是您失去了能够通过更改配置文件来切换实现的优势,这也是我们首先使用 IoC 的原因之一。

现在似乎有两种主要的方法可以在实现之间切换:

  1. 使用限定符

你可以在你的实现上添加一个注解,在你的注入点上再添加一个注解,这将告诉容器你想使用哪个。不过,您仍然需要在两个地方更改代码,因此这与实现子接口并按类型连接它是相同的。它仍然是硬编码的。

  1. 使用 bean 配置器

Spring 有这个 beanconfigurer 概念,它只是替换了旧的 xml 文件。您可以在某个类中处理配置,该类将告诉容器如何连接。我看不出与旧样式相比的优势(因此,xml 语法更具可读性),但我想这是一个品味问题。

对我来说,以体面的方式使用按类型自动装配的唯一方法是使用类路径,这样您就可以通过包含不同的类来弹出模拟而不是实现。但是由于 java classpath 有这样一个用户友好的界面,我也不认为这比旧的 xml 处理方式更容易。

所以最后,我认为这一切都归结为品味问题。是的,使用注释自动装配要容易得多,但正如您所说,它确实将您的配置硬编码到您的代码中。问题变成了,它是否真的经常改变它需要一种“软编码”方法?

于 2010-12-17T14:37:01.633 回答
2

回应评论,以语义 bean 名称代替“usedService”和“notUsedService”的示例。一个通用系统会有一些数据在服务器之间分片,但有些只存储在一个地方。

@Autowired
@Qualifier("customerDataSource")
DataSource ds;

@Autowired
@Qualifier("geoipDataSource")
DataSource geoip;

在xml中:

<bean id="customerDataSource" class="...ShardedDataSource">
  <property name="dataSources">
    <list>
      <value><ref local="ds1"/>
      <value><ref local="ds2"/>
    </list>
  </property>
</bean>

<bean id="ds1" class="...DataSource">
  ...
</bean>

<bean id="ds2" class="...DataSource">
  ...
</bean>

<alias name="ds2" alias="geoipDataSource"/>
于 2010-12-17T16:42:45.610 回答
0

您可以尝试按名称自动装配。这将解决您的问题。

如果您对按类型自动装配有严格的要求。然后你可以像这样指定,

<bean id="PersonBean1" class="com.mkyong.common.Person">
        <property name="name" value="mkyong1" />
        <property name="address" value="address 1" />
        <property name="age" value="28" />
    </bean>

    <bean id="PersonBean2" class="com.mkyong.common.Person">
        <property name="name" value="mkyong2" />
        <property name="address" value="address 2" />
        <property name="age" value="28" />
    </bean>

你可以在你的类中指定bean,比如,

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class Customer 
{
    @Autowired
    @Qualifier("PersonBean1")
    private Person person;
    private int type;
    private String action;
    //getter and setter methods
}

希望这能解决您的问题。

于 2010-12-17T14:13:28.587 回答