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

问题描述:

我们的项目使用弹簧DI/IoC,所以我使用自动装配来注入豆类。该程序需要在实例化过程中将参数传递给对象。参数在运行时已知(不在编译时)。如何在使用弹簧自动布线时传递构造函数参数?

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

接口 - 即时聊天

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)如何更换

即时聊天sayHelloServiceClassicWay =新SayHelloService(创建时间);

带有弹簧等效代码。

+0

为变量创建一个getter和setter,然后在autowired字段上使用setter方法。 – user641887

+0

在您的配置xml中,将SayHelloService的bean中的“creationTime”属性指定为constructor-arg。 Spring将自动装入它。 – Coder

+0

@ user641887,你可以添加一些代码PLZ。 – samshers

它的工作方式不同,在构造函数参数的Spring上下文中创建SayHelloService,然后Spring将自动装入它。无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

+0

你可以请添加一些代码演示。它会是运行时。进一步我的项目不想避免xml配置。但任何方式plz分享你想要的。 – samshers

+0

thx回复。代码片段'return new B2(1);'value'1'仍然是编译时,我需要在运行时传递它。 – samshers

+0

这不是必须的编译时间,你可以从属性中获取该值。但是如果你说你需要在运行时注入一个bean(B2) - 你可以通过编程来完成,Spring没有任何帮助,Spring的初始化在上下文构造 –

Spring不会以这种方式工作的构造。

您的两个bean在执行和实例化方面过于耦合:第一个bean在构建时创建,第二个在运行时在参数构造函数中传递给它一个生成值。

即使通过依赖注入顺序(@DependsOn@Order或两个@Configuration哪一个取决于其他的)它不会解决,因为运行时生成的值不是依赖你的问题,玩。

作为一种变通方法,提供了一个方法,以重视在IMessage接口一旦creationTime可能是可接受的。
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。

+0

gr8中再次回答。我仍然看到构造函数的自动装配是一条路。否则自动布线器可能是其他选择。 – samshers

+0

@samshers谢谢。我试图改进一点。问题的原因还不够清楚。安装者也是可能的,但它为客户端提供了更多的“权利”。如果它不是问题,它是有效的。 – davidxxx