Spring构造器注入

通过构造器注入设置Bean属性的示例
本文介绍如何使用构造器注入在Spring中设置Bean的属性。以User类为例,展示了通过构造器注入来设置name、age和country属性的方法,并解释了如何避免构造方法冲突及参数类型不匹配的问题。

(转自:http://javasight.net/2011/05/spring-contructor-inject-example/

 

 

 

 

在本示例中你将学到如何通过构造器注入来设置bean的属性。考虑如下的User bean类。

 

package net.javasight.designpattern.spring;

public class User {
        private String name;
        private int age;
        private String country;

        User(String name, int age, String country) {
                this.name = name;
                this.age = age;
                this.country = country;
        }

        public String toString() {
                return name + " is " + age + " years old, living in " + country;
        }
}

User类有三个属性:name, age,country。所有的三个属性是通过构造器注入来设置。User的toString()方法覆盖来展示用户对象信息。

下面是beans.xml你勇于Spring的配置。下面的代码展示了如何通过构造器来设置属性值。

<?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="user" class="net.javasight.designpattern.spring.User">
                <constructor-arg value="Eswar" />
                <constructor-arg value="24" />
                <constructor-arg value="India" />
        </bean>
</beans>

bean中的constructor-arg元素用于通过构造器注入来设置属性。因为User类中只有一个构造器,所以该代码没有任何问题。当有相同个数的构造方法时,将会出现冲突。考虑如下代码:

        User(int age, String country) {
                this.age = age;
                this.country = country;
        }

        User(String name, String country) {
                this.name = name;
                this.country = country;
        }

下面是配置文件。

        <bean id="user" class="net.javasight.designpattern.spring.User">
                <constructor-arg value="24" />
                <constructor-arg value="India" />
        </bean>

那么现在你认为哪个构造器将被调用?第一个带有int和String参数的,是吧?但是你将惊讶于Spring将调用第二个构造方法。即使我们知道第一个参数是int第二个参数是String,spring将其都解析为String。要避免该冲突,你需要定义constructor-arg的 type 属性。现在如下配置,第一个构造方法将被调用。

        <bean id="user" class="net.javasight.designpattern.spring.User">
                <constructor-arg type="int" value="24" />
                <constructor-arg type="java.lang.String" value="India" />
        </bean>

那么现在考虑如下情况。我们在User类中有如下的构造方法

        User(String name, int age) {
                this.name = name;
                this.age = age;
        }

        User(int age, String country) {
                this.age = age;
                this.country = country;
        }

配置文件如下.

<bean id="user" class="net.javasight.designpattern.spring.User">
        <constructor-arg type="int" value="24" />
        <constructor-arg type="java.lang.String" value="India" />
</bean>

那么现在你认为哪个构造方法将被调用?第二个,是吗?但是你将又一次吃惊,这是因为在调用构造方法配置文件中定义的参数顺序不做考虑。要解决该问题,需要指定index

下面是增加了index属性的配置文件:

<bean id="user" class="net.javasight.designpattern.spring.User">
        <constructor-arg index="0" type="int" value="24" />
        <constructor-arg index="1" type="java.lang.String"
                value="India" />
</bean>

现在,如我们所期待的,第二个构造方法将被调用.

### 如何在Spring中实现构造器注入Spring框架中,构造器注入是一种常用的依赖注入方式。通过这种方式,可以确保对象在其生命周期内不可变,并且强制执行所需的依赖项。 #### 构造器注入的基础概念 当类只有一个带参数的构造方法时,Spring会自动将其用于依赖注入[^1]。如果存在多个具有相同数量参数的构造函数,则可能会引发构造函数注入类型的歧义问题[^2]。这是因为Spring无法明确区分哪个构造函数应该被调用[^4]。 #### 示例代码展示 下面是一个简单的例子来说明如何使用构造器注入: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MyService { private final AnotherService anotherService; // 单一构造函数,Spring 将自动注入 AnotherService 的实例 @Autowired public MyService(AnotherService anotherService) { this.anotherService = anotherService; } public void performAction() { System.out.println("Performing action using " + anotherService); } } ``` 在这个例子中,`MyService` 类有一个带有 `AnotherService` 参数的单一构造函数。由于这是唯一的构造函数,Spring 容器会在创建 `MyService` 实例时自动注入 `AnotherService` 的实例。 #### 多个构造函数的情况处理 如果有多个构造函数,可以通过指定 `@Autowired` 注解以及提供更具体的类型提示来解决潜在的模糊性问题。例如: ```java import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class ComplexService { private final AnotherService serviceA; private final YetAnotherService serviceB; // 提供两个构造函数并标注其中一个为主构造函数 @Autowired public ComplexService(@Qualifier("serviceA") AnotherService serviceA, YetAnotherService serviceB) { this.serviceA = serviceA; this.serviceB = serviceB; } public void doSomethingComplex() { System.out.println("Using services: " + serviceA + ", " + serviceB); } // 辅助构造函数不会被 Spring 自动选择 public ComplexService(YetAnotherService serviceB) { this(null, serviceB); } } ``` 这里展示了两种不同的构造函数定义情况下的解决方案。主要依靠的是 `@Qualifier` 和其他类似的注解工具帮助消除可能存在的二义性[^3]。 #### 结合Lombok简化开发过程 为了进一步减少样板代码量,可以考虑结合 Lombok 库中的 `@RequiredArgsConstructor` 注解一起使用。这不仅能够自动生成必要的构造函数,还能保持代码简洁明了。 ```java import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor public class SimplifiedService { private final AnotherService anotherService; public void simpleOperation() { System.out.println("Executing operation via dependency injected by constructor."); } } ``` 在这种情况下,无需手动编写任何构造函数声明,因为它们会被 Lombok 自动生成出来。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值