【问题标题】:How to pass parameters dynamically to Spring beans如何将参数动态传递给 Spring bean
【发布时间】:2013-06-04 12:34:41
【问题描述】:

我是 Spring 新手。

这是bean注册的代码:

<bean id="user" class="User_Imple"> </bean>
<bean id="userdeff" class="User"> </bean>

这是我的 bean 类:

public class User_Imple implements Master_interface {

    private int id;
    private User user; // here user is another class

    public User_Imple() {
        super();
    }

    public User_Imple(int id, User user) {
        super();
        this.id = id;
        this.user = user;
    }

    // some extra functions here....
}

这是我执行操作的主要方法:

public static void main(String arg[]) {

    ApplicationContext context = new ClassPathXmlApplicationContext("/bean.xml");
    Master_interface master = (Master_interface)context.getBean("user");

    // here is my some operations..
    int id = ...
    User user = ...

    // here is where i want to get a Spring bean
    User_Imple userImpl; //want Spring-managed bean created with above params
}

现在我想用参数调用这个构造函数,这些参数是在我的主要方法中动态生成的。这就是我想要动态传递的意思——而不是静态传递,就像在我的bean.config 文件中声明的那样。

【问题讨论】:

    标签: java spring javabeans


    【解决方案1】:

    如果我猜对了,那么正确的答案是使用getBean(String beanName, Object... args) 方法,该方法会将参数传递给 bean。我可以告诉你,它是如何为基于 Java 的配置完成的,但你必须了解它是如何为基于 XML 的配置完成的。

    @Configuration
    public class ApplicationConfiguration {
          
      @Bean
      @Scope("prototype")  // As we want to create several beans with different args, right?
      String hello(String name) {
        return "Hello, " + name;
      }
    }
    
    // and later in your application
    
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
    String helloCat = (String) context.getBean("hello", "Cat");
    String helloDog = (String) context.getBean("hello", "Dog");
    

    这就是你要找的东西吗?


    更新

    这个答案得到了太多的支持,没有人看我的评论。尽管它是问题的解决方案,但它被视为 Spring 反模式,您不应该使用它!有几种不同的方法可以使用工厂、查找方法等来正确处理事情。

    请使用以下 SO 帖子作为参考:

    【讨论】:

    • 请注意,当使用“DI”时,这不是最好的解决方案,因为实际上这里我们有一个“服务定位器”(与 DI 相反)。通常,当你遇到太多的 context.getBean 时,就意味着做错了事情。
    【解决方案2】:

    请查看Constructor injection

    另外,查看IntializingBeanBeanPostProcessor 以了解springbean 的其他生命周期拦截。

    【讨论】:

    • 您能否引用参考资料说明为什么setter 注入优于构造函数
    • "Spring 团队通常提倡构造函数注入,因为它使人们能够将应用程序组件实现为不可变对象并确保所需的依赖项不为空...Setter 注入应该主要仅用于可选依赖项可以在类中分配合理的默认值” - docs.spring.io/spring-framework/docs/current/…
    • 我认为“动态”用户意味着他想在 main 方法中传递参数,或者通常在获取 bean 时。调用 getBean(...) 并直接传递参数可以工作,但是可以将此调用移动到定位器(服务定位器模式)以避免代码中对 Spring Framework 的依赖。 Locator 可以作为 bean 传入,ApplicationContextAware 定位器可以调用 getBean(bean, arg1, arg2...)。 Bean 范围应该是“原型”。另见:stackoverflow.com/questions/812415/…
    【解决方案3】:

    我认为上面提出的使用构造函数注入/setter 注入的答案对于您正在寻找的用例来说并不完美。 Spring 或多或少为构造函数/设置器采用静态参数值。我没有看到动态传递值以从 Spring Container 获取 Bean 的方法。 但是,如果您想动态获取 User_Imple 的实例,我建议使用工厂类 User_Imple_Factory

    public class User_Imple_factory { private static ApplicationContext context =new ClassPathXmlApplicationContext("/bean.xml"); public User_Imple createUserImple(int id) { User user = context.getBean("User"); return new User_Imple(id, user); } }

    【讨论】:

    • 实现 ApplicationContextAware 以避免创建可能在其他地方创建的新 ApplicationContext。
    【解决方案4】:

    构造函数注入可以帮助你。在这种情况下,您可能需要生成一个带有 ID 和用户作为其属性的 POJO,并将 POJO 传递给构造函数。在配置文件中的构造函数注入中,您可以使用 pojo 作为参考来引用此构造函数。因此,您将处理 ID 和 User 中数据的动态值。

    希望对你有帮助!!

    【讨论】:

      【解决方案5】:

      也许让User_Imple 成为普通的 Pojo(而不是 Spring bean)可以解决您的问题?

      <!-- Only use User as a Spring Bean -->
      <bean id="userdeff" class="User"></bean>
      

      Java:

      public static void main(String arg[])
      {
          ApplicationContext context =new ClassPathXmlApplicationContext("/bean.xml");
          User user = context.getBean(User.class);
      
          int id = // dynamic id
          Master_interface master = new User_Imple(id, user);
      }
      

      【讨论】:

      • 你很好@matsev,如果我没有少的话。类中我们直接使用 POJO,但在 MVC 中我们完全隐藏了业务文件..然后我们通过 bean..
      • 那么你需要一个可以从 Spring 中引用的工厂类。 Spring 仅使用(或多或少)单例
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-02
      • 2018-08-15
      • 1970-01-01
      • 1970-01-01
      • 2014-07-23
      • 2011-04-15
      • 2012-02-13
      相关资源
      最近更新 更多