使用xml配置在spring core中自动发送冲突

问题描述 投票:7回答:2

作为参考Spring @Autowired and @Qualifier

我们有这个例子来修复自动装配冲突:

public interface Vehicle {
     public void start();
     public void stop();
}

有两个豆,CarBike实现Vehicle接口。

@Component(value="car")
public class Car implements Vehicle {

     @Override
     public void start() {
           System.out.println("Car started");
     }

     @Override
     public void stop() {
           System.out.println("Car stopped");
     }
 }

@Component(value="bike")
public class Bike implements Vehicle {

     @Override
     public void start() {
          System.out.println("Bike started");
     }

     @Override
     public void stop() {
          System.out.println("Bike stopped");
     }
}

@Component
public class VehicleService {

    @Autowired
    @Qualifier("bike")
    private Vehicle vehicle;

    public void service() {
         vehicle.start();
         vehicle.stop();
    }
}

这是解决这个问题的一个很好的例子。

但是当我遇到同样的问题但在应用程序上下文中没有这些应答:

<context:component-scan></context:component-scan>
<context:annotation-config></context:annotation-config>

所有问题都通过使用@Qualifier注释来解决,但在我的情况下,我们不使用允许使用注释的应答器。

问题是 :

如何使用应用程序上下文中的配置解决此问题,就是这样,而不使用注释?

我搜索了很多,I found people talking about autowire attribute in the bean declaration <bean id="dao" class="package.IDao" autowire="byName"></bean>,我需要更多的解释。

java spring dependency-injection
2个回答
7
投票

如何仅使用应用程序上下文中的配置来解决此问题?

您可以使用下面的qualifier标签(请参阅https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers

<context:annotation-config/>
  <beans>
    <bean class="your_pkg_route.Vehicle">
      <qualifier value="bike"/>
    </bean>
  </beans>
</context:annotation-config>

我发现人们在bean声明中谈论autowire属性,我需要更多解释

使用注释

在bean声明方法上使用的@Autowired通过(另一个)声明的bean注入定义的依赖项。现在,如果您的依赖项位于应用程序的相同上下文中,则根本不需要使用@Autowired注释,因为Spring能够自行解决它们。因此,如果您的依赖项不在您的应用程序上下文中,那么您可以使用它。

例如,以下代码作为参考:

@Autowired
@Bean
public MyBean getMybean(Dependency1 depdency1, Dependency2 depdency2) {
    return new MyBean(depdency1.getSomeStuff(), depdency2.getSomeOtherStuff());
}

在这里,@Autowired将找到Dependency1Dependency2的一个实例,并将提供它们来创建MyBean的实例。

使用xml配置

来自Pro Spring 5 ... Spring支持五种自动装配模式。

  • byName:当使用byName自动装配时,Spring会尝试将每个属性连接到同名的bean。因此,如果目标bean具有名为foo的属性并且在foo中定义了ApplicationContext bean,则将foo bean分配给目标的foo属性。
  • byType:当使用byType自动装配时,Spring会尝试通过在ApplicationContext中自动使用相同类型的bean来连接目标bean上的每个属性。
  • constructor:这个功能就像byType布线一样,除了它使用构造函数而不是setter来执行注入。 Spring尝试匹配构造函数中可以包含的最大数量的参数。所以,如果你的bean有两个构造函数,一个接受String,另一个接受StringInteger,你的String中有IntegerApplicationContext bean,Spring使用双参数构造函数。
  • default:Spring将自动在constructorbyType模式之间进行选择。如果你的bean有一个默认的(无参数)构造函数,Spring使用byType;否则,它使用构造函数。
  • no:这是默认值

所以,在你的情况下,你需要做这样的事情(但是,我不推荐它。为什么?,你需要将Vehicle类声明为bean和不正确的组件,请参阅Spring: @Component versus @Bean。另一方面我不确定你是否可以使用它只是将它声明为bean):

// xml config
<context:annotation-config/>
  <beans>

    // use the primary tag here too! in order to say this the primary bean
    // this only works when there are only two implementations of the same interface
    <bean id="bike" primary="true" class="your_pkg_route.Bike"/>
    <bean id="car" class="your_pkg_route.Car"/>         

    <bean autowire="byName" class="your_pkg_route.VehicleService"/>

  <beans>
</context:annotation-config>

// VehicleService
@Component
public class VehicleService {

    private Vehicle bike;   // call attribute 'bike' so it is autowired by its name

    public void service() {
         //...
    }
}

正如您所看到的那样,使用xml配置尝试执行此操作时会遇到很多问题,因此我建议您尽可能使用注释选项。

相关文章:

PS:我没有测试任何发布的代码。


5
投票

您可以使用@Primary而不是@Qualifier

@Primary
@Component(value="bike")
public class Bike implements Vehicle {

当有多个相同类型的bean时,我们使用@Primary给bean更高的优先级。

我们可以直接在bean上使用@Primary

您还可以在XML中设置主要属性:

属性具有主要属性:

<bean primary="true|false"/>

如果通过XML声明了@ Primary-annotated类,则会忽略@Primary注释元数据,而是被尊重。