spring:在使用@Autowired和上下文自动连接原型bean时,如何使用非默认构造函数:组件扫描?

2022-09-03 00:37:44

假设您有一个原型 Bean 类,如下所示:

@Component
@Scope("prototype")
public class Foobar {
    private String foo;
    public Foobar( String foo ) {
        this.foo = foo;
    }
}

那么,是否可以在另一个类中使用这样的bean来连接,该类应该使用非默认构造函数来实例化Bean?@AutowiredFoobar(String foo)

update
在上面的示例中,构造函数参数 、 在应用程序上下文中不可用,而是动态的。因此,使用构造函数进行注释,然后在上下文中的某个位置指定构造函数似乎不是理想的解决方案。String foo@Autowiredfoo


答案 1

以下是3种方法,只需看看适合您情况的最佳方法:

使用@Autowired构造函数

更好的情况是:您拥有在上下文中构建原型Bean所需的一切(即使对于诸如@Value("${prop}"))

如果你想要一种自动的方式来做到这一点,你将需要拥有在上下文中实例化bean所需的一切(即使对于原型Bean也是如此)。如果你在你的上下文中有一切需要的东西,你可以简单地注释构造函数,因为Spring将为你做剩下的工作。@Autowired

@Component
@Scope("prototype")
public class FooBar {

    private Baz baz;

    @Autowired
    public FooBar(Baz baz) {
        this.baz = baz;
    }

}

FactoryBeans

更好的情况是:如果您使用的是基于 XML 的上下文,则会更喜欢这种方式。

另一种可能性,如果你需要一个个性化的方式来做到这一点,那就是使用s。从文档中FactoryBean

由BeanFactory中使用的对象实现的接口,这些对象本身就是工厂。如果 Bean 实现此接口,则它被用作要公开的对象的工厂,而不是直接用作将自身公开的 Bean 实例。

Spring只使用它来构建您请求的对象(无论是原型还是单例)。FactoryBean

对于您的情况,您可以有一个如下实现:

@Component
public class FooBarFactory implements FactoryBean<FooBar> {

    @Autowired
    private Baz myContextProvidedObject;

    @Override
    public FooBar getObject() throws Exception {
        return new FooBar(myContextProvidedObject, "my parameter");
    }

    @Override
    public Class<?> getObjectType() {
        return FooBar.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

}

你可以简单地处理你的上下文的其他实例。@AutowiredFooBar

@Configuration

更好的情况是:如果您已经使用注释配置了上下文,那么您肯定会更喜欢这种方式。

第三种方法,这是我最喜欢的,是使用你的类。从文档中@Configuration

public @interface Configuration:指示类声明一个或多个@Bean方法,并且可以由Spring容器处理,以在运行时为这些bean生成bean定义和服务请求,例如:

在该类中,您可以有一个如下方法:

@Configuration
public class MyConfig {

    @Bean
    @Scope("prototype")
    public FooBar fooBar(Baz myContextProvidedObject) {
        return new FooBar(myContextProvidedObject, "my parameter");
    }

}

答案 2

您需要使用@Autowired对构造函数进行注释,并且对于在 Bean 实例化时必须传递给构造函数的参数,您必须使用非基元类型参数:

例如:

@Component
@Scope("prototype")
public class FooBar {

    private DataSource data;

    @Autowired
    public FooBar(DataSource data) {
        this.bdata = data;
    }
}

然后使用以下内容注释数据源:

@Component("dataSupplier")
public class DataSource {

    public int getData() {}
}

推荐