有没有办法 @Autowire 需要构造函数参数的 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;
....
}
在此示例中,如何使用 @Autowire 注释指定 MyBeanService 中“constrArg”的值?有什么办法可以做到这一点吗?
谢谢,
埃里克
I'm using Spring 3.0.5 and am using @Autowire annotation for my class members as much as possible. One of the beans that I need to autowire requires arguments to its constructor. I've looked through the Spring docs, but cannot seem to find any reference to how to annotate constructor arguments.
In XML, I can use as part of the bean definition. Is there a similar mechanism for @Autowire annotation?
Ex:
@Component
public class MyConstructorClass{
String var;
public MyConstructorClass( String constrArg ){
this.var = var;
}
...
}
@Service
public class MyBeanService{
@Autowired
MyConstructorClass myConstructorClass;
....
}
In this example, how do I specify the value of "constrArg" in MyBeanService with the @Autowire annotation? Is there any way to do this?
Thanks,
Eric
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
您需要
@Value
注释。参见: 表达式语言>注释配置
更清楚地说:在您的场景中,您将连接两个类,
MybeanService
和MyConstructorClass
,如下所示:更新:如果您需要多个类具有不同值的
MyConstructorClass
的不同实例,您应该 使用限定符注释You need the
@Value
annotation.See: Expression Language > Annotation Configuration
To be more clear: in your scenario, you'd wire two classes,
MybeanService
andMyConstructorClass
, something like this:Update: if you need several different instances of
MyConstructorClass
with different values, you should use Qualifier annotations嗯,我有时会遇到同样的问题。据我所知,当想要向构造函数添加动态参数时,无法做到这一点。然而,工厂模式可能会有所帮助。
现在,
MyBean
本身并不是 spring bean,但它已经足够接近了。依赖注入是有效的,尽管我注入的是工厂而不是 bean 本身——如果想要替换它,就必须在自己的新MyBean
实现之上注入一个新工厂。此外,
MyBean
可以访问其他 bean - 因为它可以访问工厂的自动装配内容。人们显然可能想向 getMyBean 函数添加一些逻辑,这是我允许的额外努力,但不幸的是我没有更好的解决方案。由于问题通常是动态参数来自外部源,例如数据库或用户交互,因此我必须仅在运行中实例化该 bean,只有当该信息随时可用时,所以
Factory< /code> 应该足够了。
Well, from time to time I run into the same question. As far as I know, one cannot do that when one wants to add dynamic parameters to the constructor. However, the factory pattern may help.
Now,
MyBean
is not a spring bean per se, but it is close enough. Dependency Injection works, although I inject the factory and not the bean itself - one has to inject a new factory on top of his own newMyBean
implementation if one wants to replace it.Further,
MyBean
has access to other beans - because it may have access to the factory's autowired stuff.And one might apparently want to add some logic to the
getMyBean
function, which is extra effort I allow, but unfortunately I have no better solution. Since the problem usually is that the dynamic parameters come from an external source, like a database, or user interaction, therefore I must instantiate that bean only in mid-run, only when that info is readily available, so theFactory
should be quite adequate.不,不是按照你的意思。表示
MyConstructorClass
的 bean 必须是可配置的,而不需要任何客户端 bean,因此MyBeanService
对于如何配置MyConstructorClass
没有发言权。这不是一个自动装配问题,这里的问题是 Spring 如何实例化
MyConstructorClass
,假设MyConstructorClass
是一个@Component
(而你'正在使用组件扫描,因此没有在配置中显式指定MyConstructorClass
)。正如 @Sean 所说,这里的一个答案是在构造函数参数上使用
@Value
,以便 Spring 将从系统属性或属性文件中获取构造函数值。另一种方法是让MyBeanService
直接实例化MyConstructorClass
,但如果这样做,那么MyConstructorClass
就不再是 Spring bean。No, not in the way that you mean. The bean representing
MyConstructorClass
must be configurable without requiring any of its client beans, soMyBeanService
doesn't get a say in howMyConstructorClass
is configured.This isn't an autowiring problem, the problem here is how does Spring instantiate
MyConstructorClass
, given thatMyConstructorClass
is a@Component
(and you're using component-scanning, and therefore not specifying aMyConstructorClass
explicitly in your config).As @Sean said, one answer here is to use
@Value
on the constructor parameter, so that Spring will fetch the constructor value from a system property or properties file. The alternative is forMyBeanService
to directly instantiateMyConstructorClass
, but if you do that, thenMyConstructorClass
is no longer a Spring bean.您还可以像这样配置您的组件:
使用 Bean 注释,您可以告诉 Spring 在 BeanFactory 中注册返回的 bean。
所以你可以根据需要自动装配它。
You can also configure your component like this :
With the
Bean
annotation, you are telling Spring to register the returned bean in theBeanFactory
.So you can autowire it as you wish.
另一种方法是不将参数传递给构造函数,而是将它们作为 getter 和 setter,然后在 @PostConstruct 中根据需要初始化值。在这种情况下,Spring 将使用默认构造函数创建 bean。下面是一个例子
An alternative would be instead of passing the parameters to the constructor you might have them as getter and setters and then in a @PostConstruct initialize the values as you want. In this case Spring will create the bean using the default constructor. An example is below
大多数答案都相当古老,所以当时可能不可能,但实际上有一个解决方案可以满足所有可能的用例。
所以正确的答案是:
@Value
你必须在配置文件中的某处拥有该值)解决这些问题的方法是使用
ApplicationContext
手动创建对象:这是一个很酷的解决方案,因为:
@Autowired
,还有@Async
例如),唯一要记住的是,您必须有一个在要实例化的类中不带任何参数(并且可以为空)的构造函数(或者如果需要,则为
@Autowired
构造函数)。Most answers are fairly old, so it might have not been possible back then, but there actually is a solution that satisfies all the possible use-cases.
So right know the answers are:
@Value
you have to have the value in a configuration file somewhere)The solution to solve those issues is to create the object manually using the
ApplicationContext
:This is a cool solution because:
@Autowired
obviously, but also@Async
for example),The only thing to keep in mind is that you have to have a constructor that takes no arguments (and that can be empty) in the class you want to instantiate (or an
@Autowired
constructor if you need it).另一种选择是,如果您已经创建了对象的实例,并且想要将其添加为 @autowired 依赖项以初始化所有内部 @autowired 变量,则可能如下所示:
Another alternative, if you already have an instance of the object created and you want to add it as an @autowired dependency to initialize all the internal @autowired variables, could be the following:
我喜欢 Zakaria 的答案,但是如果您所在的项目中您的团队不想使用这种方法,并且您必须尝试使用字符串、整数、浮点数或基本类型从属性文件构建某些内容,构造函数,然后您可以在构造函数中的参数上使用 Spring 的
@Value
注解。例如,我遇到了一个问题,我试图将字符串属性拉入用
@Service
注释的类的构造函数中。我的方法适用于@Service
,但我认为这种方法应该适用于任何 spring java 类,如果它有注释(例如@Service
、@Component
等),这表明 Spring 将是构造该类实例的一个。假设在某个 yaml 文件(或您正在使用的任何配置)中,您有这样的内容:
并且您有一个构造函数:
这不会运行,因为 Spring 将无法找到字符串
envProperty
。因此,这是获取该值的一种方法:在上面的构造函数中,Spring 将调用该类并知道使用从我的 yaml 配置中提取的 String
"property-for-dev-environment"
调用它。注意:我相信 @Value 注释适用于字符串、整数,并且我相信原始类型。如果您尝试传递自定义类(bean),则可以使用上面定义的答案中的方法。
I like Zakaria's answer, but if you're in a project where your team doesn't want to use that approach, and you're stuck trying to construct something with a String, integer, float, or primative type from a property file into the constructor, then you can use Spring's
@Value
annotation on the parameter in the constructor.For example, I had an issue where I was trying to pull a string property into my constructor for a class annotated with
@Service
. My approach works for@Service
, but I think this approach should work with any spring java class, if it has an annotation (such as@Service
,@Component
, etc.) which indicate that Spring will be the one constructing instances of the class.Let's say in some yaml file (or whatever configuration you're using), you have something like this:
and you've got a constructor:
This won't run as Spring won't be able to find the string
envProperty
. So, this is one way you can get that value:In the above constructor, Spring will call the class and know to use the String
"property-for-dev-environment"
pulled from my yaml configuration when calling it.NOTE: this I believe @Value annotation is for strings, intergers, and I believe primative types. If you're trying to pass custom classes (beans), then approaches in answers defined above work.
您需要使用@Autowired 和@Value。请参阅此帖子了解更多信息这个话题。
You need to use @Autowired and @Value. Refer this post for more information on this topic.