是否有办法@Autowire需要构造函数参数的bean?

Eri*_* B. 102 spring constructor autowired spring-annotations spring-bean

我正在使用Spring 3.0.5并尽可能地为我的班级成员使用@Autowire注释.我需要自动装配的bean之一需要其构造函数的参数.我查看了Spring文档,但似乎找不到任何关于如何注释构造函数参数的引用.

在XML中,我可以将其用作bean定义的一部分.@Autowire注释是否有类似的机制?

例如:

@Component
public class MyConstructorClass{

  String var;
  public MyConstructorClass( String constrArg ){
    this.var = var;
  }
...
}


@Service
public class MyBeanService{
  @Autowired
  MyConstructorClass myConstructorClass;

  ....
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,如何使用@Autowire注释在MyBeanService中指定"constrArg"的值?有没有办法做到这一点?

谢谢,

埃里克

Sea*_*oyd 58

你需要@Value注释.

常见用例是使用"#{systemProperties.myProp}"样式表达式指定默认字段值 .

public class SimpleMovieLister {

  private MovieFinder movieFinder;
  private String defaultLocale;

  @Autowired
  public void configure(MovieFinder movieFinder, 
                        @Value("#{ systemProperties['user.region'] }"} String defaultLocale) {
      this.movieFinder = movieFinder;
      this.defaultLocale = defaultLocale;
  }

  // ...
}
Run Code Online (Sandbox Code Playgroud)

请参阅: 表达式语言>注释配置


更清楚一点:在你的场景中,你将连接两个类,MybeanService并且MyConstructorClass,像这样:

@Component
public class MyBeanService implements BeanService{
    @Autowired
    public MybeanService(MyConstructorClass foo){
        // do something with foo
    }
}

@Component
public class MyConstructorClass{
    public MyConstructorClass(@Value("#{some expression here}") String value){
         // do something with value
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:如果您需要MyConstructorClass具有不同值的多个不同实例,则应使用限定符注释

  • 感谢您的提示,但我不明白这与为注入的 bean 设置构造函数 arg 有何关系。从我从 spring 文档中可以看出,它适用于设置默认值,但没有指定如何传递构造函数 arg。 (2认同)
  • @EricB.对于字符串参数,`@ Value`就像`@Autowired`. (2认同)

小智 11

好吧,我不时会遇到同样的问题.据我所知,当想要向构造函数添加动态参数时,不能这样做.但是,工厂模式可能有所帮助.

public interface MyBean {
    // here be my fancy stuff
}

public interface MyBeanFactory {
    public MyBean getMyBean(/* bean parameters */);
}

@Component
public class MyBeanFactoryImpl implements MyBeanFactory {
    @Autowired
    WhateverIWantToInject somethingInjected;

    public MyBean getMyBean(/* params */) {
        return new MyBeanImpl(/* params */);
    }

    private class MyBeanImpl implements MyBean {
        public MyBeanImpl(/* params */) {
            // let's do whatever one has to
        }
    }
}

@Component
public class MyConsumerClass {
    @Autowired
    private MyBeanFactory beanFactory;

    public void myMethod() {
        // here one has to prepare the parameters
        MyBean bean = beanFactory.getMyBean(/* params */);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,MyBean它本身不是一个春豆,但它足够接近.依赖注入工作,虽然我注入工厂而不是bean本身 - MyBean如果想要替换它,必须在他自己的新实现之上注入一个新工厂.

此外,MyBean可以访问其他bean - 因为它可以访问工厂的自动装配的东西.

人们可能显然想在getMyBean函数中添加一些逻辑,这是我允许的额外努力,但不幸的是我没有更好的解决方案.由于问题通常是动态参数来自外部源,如数据库或用户交互,因此我必须仅在中期运行时实例化该bean,只有当该信息随时可用时,所以Factory应该是足够的.


ska*_*man 9

在此示例中,如何MyBeanService使用@Autowire注释指定"constrArg"的值?有没有办法做到这一点?

不,不是你的意思.表示的bean MyConstructorClass必须是可配置的,不需要任何客户端bean,因此MyBeanService不会对MyConstructorClass配置方式有所了解.

这不是一个自动装配问题,这里的问题是Spring如何实例化MyConstructorClass,因为它MyConstructorClass是一个@Component(并且你正在使用组件扫描,因此没有MyConstructorClass在你的配置中明确指定).

正如@Sean所说,这里的一个答案是使用@Value构造函数参数,以便Spring从系统属性或属性文件中获取构造函数值.替代方法是MyBeanService直接实例化MyConstructorClass,但如果你这样做,那么MyConstructorClass就不再是Spring bean了.


Zak*_*ria 5

您还可以像这样配置您的组件:

package mypackage;
import org.springframework.context.annotation.Configuration;
   @Configuration
   public class MyConstructorClassConfig {


   @Bean
   public MyConstructorClass myConstructorClass(){
      return new myConstructorClass("foobar");
   }
  }
}
Run Code Online (Sandbox Code Playgroud)

使用Bean注释,您告诉Spring将返回的bean注册到中BeanFactory

因此,您可以根据需要为其自动接线。