【问题标题】:Spring autowire byType vs constructor ( xml configuration)Spring autowire byType vs 构造函数(xml配置)
【发布时间】:2018-01-28 08:07:28
【问题描述】:

我有一个问题。关于“Spring autowire byType vs constructor(xml配置)”。

在多个地方读到构造函数自动注入类似于 byType。但是在我测试的时候,如果有歧义,构造函数 autowire 的行为类似于 byName(甚至不完全),如果我遗漏了任何重要的点,需要您的输入。

我有以下配置:

<bean name="customerRepository" class="repository.HibernameCustomerRepositoryImpl"/>
<bean name="customerRepository1" class="repository.EclipselinkCustomerRepositoryImpl"/>
<bean name="customerService" class="service.CustomerServiceImpl" autowire="..."/>

按类型输出: org.springframework.beans.factory.NoUniqueBeanDefinitionException [良好预期输出]

构造函数输出: pankaj [注意我没有收到 NoUniqueBeanDefinitionException,它为我提供了 customerRepository 的输出,为什么?下面是示例代码] [似乎在有歧义的情况下,它会检查属性名称并选择名称与属性名称匹配的 bean]

示例代码:

public class CustomerServiceImpl implements CustomerService {

private CustomerRepository customerRepository;

public CustomerServiceImpl() {

}

public CustomerServiceImpl(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}

//  public void setCustomerRepository(CustomerRepository customerRepository) {
//  this.customerRepository = customerRepository;
//  }

@Override
public List<customer> findAll() {
return customerRepository.findAll();
}
}

【问题讨论】:

    标签: spring


    【解决方案1】:

    是的,Spring 确实按名称自动装配,但与“按名称”自动装配模式不完全一样。

    Spring Documentation 声明:

    按属性名称自动装配。 Spring 寻找与需要自动装配的属性同名的 bean。例如,如果一个 bean 定义被设置为按名称自动装配并且它包含一个主属性(即,它有一个 setMaster(..) 方法),那么 Spring 会查找一个名为 master 的 bean 定义并使用它来设置该属性。

    因此,为了按名称自动装配,应该存在 setter 方法。但是,在这种情况下,容器会将 bean 定义名称与构造函数参数的名称相匹配,以防出现歧义。

    示例:

    Motor.java

    package com.chiranth;
    public interface Motor 
    {
        public void start();
    }
    

    ElectricMotor1.java

    package com.chiranth;
    public class ElectricMotor1 implements Motor
    {
        public void start()
        {
            System.out.println("Motor 1 Started.");
        }
    }
    

    ElectricMotor2.java

    package com.chiranth;
    public class ElectricMotor2 implements Motor
    {
        public void start()
        {
            System.out.println("Motor 2 Started.");
        }
    }
    

    TeslaModelX.java

    package com.chiranth;
    public class TeslaModelX 
    {
        private Motor motor;
    
        public TeslaModelX(Motor electricMotor1)
        {
            motor=electricMotor1;
        }
    
        public void goForward()
        {
            motor.start();
            System.out.println("Going Forward.");
        }
    }
    

    Spring.xml

    <?xml version = "1.0" encoding = "UTF-8"?>
    
    <beans xmlns = "http://www.springframework.org/schema/beans"
       xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="electricMotor1" class="com.chiranth.ElectricMotor1"/>
        <bean id="electricMotor2" class="com.chiranth.ElectricMotor2"/>
    
        <bean id="modelX" class="com.chiranth.TeslaModelX" autowire="constructor"/>
    </beans>
    

    Test.java

    package com.chiranth;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class Test 
    {
        public static void main(String[] args) 
        {
            ApplicationContext context= new ClassPathXmlApplicationContext("Spring.xml");
            TeslaModelX modelX=(TeslaModelX)context.getBean("modelX");
            modelX.goForward();
        }
    }
    

    输出:

    Motor 1 Started.
    Going Forward.
    

    即使属性名与上例中的 bean 名不匹配,也实现了自动装配。

    【讨论】:

      【解决方案2】:

      是的,你是对的,当出现歧义时,Spring 会按名称自动装配。您可以使用@Qualifier 帮助 Spring 根据名称选择正确的实现。
      检查docs

      【讨论】:

        猜你喜欢
        • 2014-10-30
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 2018-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多