Spring Core与xml配置中的自动装配冲突

Med*_*edo 7 java spring dependency-injection

Spring @Autowired和@Qualifier为参考

我们有以下示例可解决自动装配冲突:

public interface Vehicle {
     public void start();
     public void stop();
}
Run Code Online (Sandbox Code Playgroud)

有两个bean,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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

<context:component-scan></context:component-scan>
<context:annotation-config></context:annotation-config>
Run Code Online (Sandbox Code Playgroud)

所有问题都可以通过使用@Qualifier注释来解决,但在我的情况下,我们不会使用允许使用注释的平台。

问题是 :

我如何仅使用应用程序上下文中的配置来解决此问题,而不使用注释

我进行了很多搜索,发现有人autowire在bean声明中谈论属性,因此<bean id="dao" class="package.IDao" autowire="byName"></bean>我需要更多解释。

lea*_*iro 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>
Run Code Online (Sandbox Code Playgroud)

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

使用注释

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

例如,参考以下代码:

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

在这里,@Autowired会发现一个实例Dependency1,并Dependency2并为他们提供创作的一个实例MyBean

使用xml配置

Pro Spring 5开始,Spring支持五种自动装配模式。

  • byName:使用byName自动装配时,Spring尝试将每个属性连接到同名的Bean。因此,如果目标Bean具有一个名为的属性,foo并且在foo中定义了一个Bean ApplicationContext,则该fooBean将分配给foo目标的属性。
  • byType:使用byType自动装配时,Spring尝试通过自动使用中的相同类型的bean 来连接目标bean上的每个属性 ApplicationContext
  • constructor:此功能类似于byType接线,除了它使用构造函数而不是setter来执行注入。Spring尝试匹配构造函数中可以匹配的最大数量的参数。因此,如果您的bean有两个构造函数,一个接受a,另一个接受a StringStringan Integer,并且您StringIntegerbean 和a都包含ApplicationContext,则Spring使用两个参数的构造函数。
  • default:Spring将自动在constructorbyType模式之间进行选择。如果您的bean具有默认(无参数)构造函数,则Spring使用 byType; 否则,它使用构造函数。
  • no:这是默认设置

因此,在您的情况下,您需要执行以下操作(但是,我不建议这样做。为什么?,您需要将Vehicleclass 声明为Bean和不正确的组件,请参见Spring:@Component与@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() {
         //...
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,尝试使用xml config进行此操作有很多麻烦,因此,如果可能的话,我建议您使用注释选项。

相关文章:

PS:我尚未测试任何发布的代码。


use*_*900 5

您可以使用@Primary代替@Qualifier

@Primary
@Component(value="bike")
public class Bike implements Vehicle {
Run Code Online (Sandbox Code Playgroud)

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

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

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

属性具有主要属性:

<bean primary="true|false"/>
Run Code Online (Sandbox Code Playgroud)

如果通过XML声明了@Primary批注的类,则@Primary批注元数据将被忽略,而是被尊重。