如何在使用弹簧自动布线时传递构造函数参数?

时间:2017-10-09 04:54:16

标签: java spring dependency-injection inversion-of-control autowired

我们的项目正在使用spring DI / IoC,因此我使用自动装配来注入bean。程序需要在实例化过程中将参数传递给对象。并且参数在运行时(不是在编译时)知道。

如何在使用自动装配时实现此目的。示例代码如下。

界面 - IMessage

package com.example.demo.services;

public interface IMessage {
        String message(String name);
}

实施 -
SayHelloService

package com.example.demo.services;

import org.springframework.stereotype.Service;

@Service
public class SayHelloService implements IMessage {

    String id;

    public SayHelloService(String id) {
        super();
        this.id = id;
    }

    @Override
    public String message(String name) {
        return "Hello Dear User - " + name + ". Greeter Id: " + id ;
    }
}

MasterService

package com.example.demo.services;

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

@Service
public class MasterService implements IMessage  {

    String creationTime;

    MasterService() {
        System.out.println("ms... default constructor");
        creationTime = Long.toString(System.currentTimeMillis());
    }

    //classic java way of creating service
    IMessage sayHelloServiceClassicWay = new SayHelloService(creationTime);

    //how to achieve above using spring auto wiring. Below code does not exactly do same.
    @Autowired
    @Qualifier("sayHelloService")
    IMessage sayHelloServiceAutoWired;

    @Override
    public String message(String name) {
        return name.toString();
    }    
}

现在在上面的程序(在MasterService中)如何替换

  

IMessage sayHelloServiceClassicWay = new SayHelloService(creationTime);

使用弹簧等效代码。

2 个答案:

答案 0 :(得分:1)

春天不会这样工作。

你的两个bean在执行和实例化方面都太耦合了:第一个是创建的,它是在构造期间创建的,第二个是它,并在运行时在参数构造函数中传递给它一个生成的值。 />

即使通过使用依赖注入顺序(@DependsOn@Order或两个@Configuration,其中一个依赖于另一个),它也不能解决您的问题,因为运行时生成的值< strong>这不是依赖。

作为一种解决方法,可以接受在creationTime界面中提供一次 IMessage的方法。
SayHelloService看起来像是:

package com.example.demo.services;

import org.springframework.stereotype.Service;

    @Service
    public class SayHelloService implements IMessage {

        String id;

        public SayHelloService(String id) {
            super();
            this.id = id;
        }

        @Override
        public void setId(String id){
            // you can add this check to enforce the immutability of id
            if (this.id != null){//exception handling}
            this.id = id;
        }

        @Override
        public String message(String name) {
            return "Hello Dear User - " + name + ". Greeter Id: " + id ;
        }
    }

你可以用这种方式改变MasterService

private IMessage sayHelloServiceAutoWired;

@Autowired
MasterService( @Qualifier("sayHelloService")
IMessage sayHelloServiceAutoWired) {
    System.out.println("ms... default constructor");
    creationTime = Long.toString(System.currentTimeMillis());
    this.sayHelloServiceAutoWired = sayHelloServiceAutoWired;
    this.sayHelloServiceAutoWired.setId(creationTime);
}

PS:自动装配构造函数不是强制性的,但没有API来设置类的依赖关系更清晰。您也可以使用setter。

答案 1 :(得分:0)

它的工作方式不同,在Spring上下文中使用构造函数args创建SayHelloService,然后Spring将自动装配它。 No-xml congif例子:

class B1 {
    @Autowired
    B2 b2;
}

class B2 {
    B2(int i) {
    }
}

@Configuration
class Config {

    @Bean
    B1 b1() {
        return new B1();
    }

    @Bean
    B2 b2() {
        return new B2(1);
    }
}

在这个例子中,Spring会自动装配B2,它具有带有一个arg的构造函数