一个 bean class 可以在里面实例化另一个 class 吗?if/how 我们应该避免吗?
Can a bean class instantiate another class inside, and if/how should we avoid it?
假设bean在这里注册。
@Configuration
public class configuration{
@Bean(name = "MyClass")
public MyClass getMyClass(@Value("avalue") final String s){
return new MyClass(s);
}
}
}
并且 class 在内部实例化了另一个 class,如下所示(两者都不需要注释吗?)
public class MyClass{
MyOtherClass myOtherClass;
public MyClass(String s){
this.myOtherClass = new MyOtherClass(s);
}
}
public class MyOtherClass{
String s;
public MyOtherClass(String s){
this.s = s;
}
}
这个机制是如何运作的?在 bean 注入中实例化一个新实例是否安全?这样做有什么好处或坏处?
如果我们通过将 MyOtherClass 也变成一个 bean 来避免使用它,会是这样吗? (主要关注:@Autowired和getMyclass()是放对地方了还是多余?)
@Configuration
public class configuration{
@Bean(name = "MyOtherClass")
public MyOtherClass getMyOtherClass(@Value("avalue") final String s){
return new MyOtherClass(s);
}
}
@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass){
//I was told the input should be myClass not myOtherClass,
//and the return is myClass not new MyClass(myOtherClass);
//since it's already autowired. Is that correct?
//What if the configuration.java and MyClass.java are in different project?
return myClass;
}
}
}
@Component
public class MyClass{
MyOtherClass myOtherClass;
@Autowired
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
public class MyOtherClass{
String s;
public MyOtherClass(String s){
this.s = s;
}
}
在 bean 注入中实例化新实例是否安全?
是的。但是,该新实例不受 Spring 管理。 (很抱歉,如果这很明显。)
但也许更重要且与 Spring 无关,这样做:
public class MyClass{
MyOtherClass myOtherClass;
public MyClass(String s){
this.myOtherClass = new MyOtherClass(s);
}
}
很难进行单元测试,因为没有简单的方法来模拟 myOtherClass
。
仍然与 Spring 无关,重构以使用 IoC 以便于进行单元测试:
public class MyClass{
private final MyOtherClass myOtherClass;
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
并将 class 配置为 Spring bean,但没有将 MyOtherClass
也配置为 bean:
@Configuration
public class Configuration{
private MyOtherClass getMyOtherClass(final String s){
return new MyOtherClass(s);
}
}
@Bean(name = "MyClass")
public MyClass getMyClass(@Value("avalue") final String s){
return new MyClass(getMyOtherClass(s));
}
}
}
您发布的关于@Component 和@Autowire 的内容会起作用,但听起来您想避免将 MyOtherClass
作为 bean 公开。
如果您不想公开您的 MyOtherClass
并控制其实例的创建,您可以使用第一种方法:
...
public MyClass(String s) {
this.myOtherClass = new MyOtherClass(s);
}
它是安全的,但它不是依赖项注入:MyOtherClass
不受 Spring 管理,因此您将无法使用 [=17= 将其注入到其他 bean 中] 或将其他 spring 管理的 类 注入 MyOtherClass
。此外,正如安德鲁所提到的,模拟 MyOtherClass
.
变得不可能
如果在 Spring 上下文中将 MyOtherClass
注册为 bean 没问题,那么最简单的方法是将 类 都注释为 @Component
并让 Spring 完成它的工作(在这种情况下你应该使用 @ComponentScan
来帮助 Spring 自动检测你的 类):
@Component
class MyClass {
MyOtherClass myOtherClass;
@Autowired
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
@Component
class MyOtherClass {
String s;
public MyOtherClass(@Value("avalue") final String s){
this.s = s;
}
}
或者,使用 @Bean
(如果 Config.java
和 MyClass.java
在不同的项目中,这将有效):
@Configuration
public class Config {
@Value("avalue")
private String s;
@Bean(name = "myClass")
public MyClass getMyClass(){
return new MyClass(getMyOtherClass());
}
@Bean(name = "myOtherClass")
public MyOtherClass getMyOtherClass() {
return new MyOtherClass(s);
}
}
注意:如果您已经使用
在 Spring 上下文中注册 MyClass
@Component
public class MyClass {
...
}
那你就不需要再做一次
@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass) {
return myClass;
}
假设bean在这里注册。
@Configuration
public class configuration{
@Bean(name = "MyClass")
public MyClass getMyClass(@Value("avalue") final String s){
return new MyClass(s);
}
}
}
并且 class 在内部实例化了另一个 class,如下所示(两者都不需要注释吗?)
public class MyClass{
MyOtherClass myOtherClass;
public MyClass(String s){
this.myOtherClass = new MyOtherClass(s);
}
}
public class MyOtherClass{
String s;
public MyOtherClass(String s){
this.s = s;
}
}
这个机制是如何运作的?在 bean 注入中实例化一个新实例是否安全?这样做有什么好处或坏处?
如果我们通过将 MyOtherClass 也变成一个 bean 来避免使用它,会是这样吗? (主要关注:@Autowired和getMyclass()是放对地方了还是多余?)
@Configuration
public class configuration{
@Bean(name = "MyOtherClass")
public MyOtherClass getMyOtherClass(@Value("avalue") final String s){
return new MyOtherClass(s);
}
}
@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass){
//I was told the input should be myClass not myOtherClass,
//and the return is myClass not new MyClass(myOtherClass);
//since it's already autowired. Is that correct?
//What if the configuration.java and MyClass.java are in different project?
return myClass;
}
}
}
@Component
public class MyClass{
MyOtherClass myOtherClass;
@Autowired
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
public class MyOtherClass{
String s;
public MyOtherClass(String s){
this.s = s;
}
}
在 bean 注入中实例化新实例是否安全?
是的。但是,该新实例不受 Spring 管理。 (很抱歉,如果这很明显。)
但也许更重要且与 Spring 无关,这样做:
public class MyClass{
MyOtherClass myOtherClass;
public MyClass(String s){
this.myOtherClass = new MyOtherClass(s);
}
}
很难进行单元测试,因为没有简单的方法来模拟 myOtherClass
。
仍然与 Spring 无关,重构以使用 IoC 以便于进行单元测试:
public class MyClass{
private final MyOtherClass myOtherClass;
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
并将 class 配置为 Spring bean,但没有将 MyOtherClass
也配置为 bean:
@Configuration
public class Configuration{
private MyOtherClass getMyOtherClass(final String s){
return new MyOtherClass(s);
}
}
@Bean(name = "MyClass")
public MyClass getMyClass(@Value("avalue") final String s){
return new MyClass(getMyOtherClass(s));
}
}
}
您发布的关于@Component 和@Autowire 的内容会起作用,但听起来您想避免将 MyOtherClass
作为 bean 公开。
如果您不想公开您的 MyOtherClass
并控制其实例的创建,您可以使用第一种方法:
...
public MyClass(String s) {
this.myOtherClass = new MyOtherClass(s);
}
它是安全的,但它不是依赖项注入:MyOtherClass
不受 Spring 管理,因此您将无法使用 [=17= 将其注入到其他 bean 中] 或将其他 spring 管理的 类 注入 MyOtherClass
。此外,正如安德鲁所提到的,模拟 MyOtherClass
.
如果在 Spring 上下文中将 MyOtherClass
注册为 bean 没问题,那么最简单的方法是将 类 都注释为 @Component
并让 Spring 完成它的工作(在这种情况下你应该使用 @ComponentScan
来帮助 Spring 自动检测你的 类):
@Component
class MyClass {
MyOtherClass myOtherClass;
@Autowired
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
@Component
class MyOtherClass {
String s;
public MyOtherClass(@Value("avalue") final String s){
this.s = s;
}
}
或者,使用 @Bean
(如果 Config.java
和 MyClass.java
在不同的项目中,这将有效):
@Configuration
public class Config {
@Value("avalue")
private String s;
@Bean(name = "myClass")
public MyClass getMyClass(){
return new MyClass(getMyOtherClass());
}
@Bean(name = "myOtherClass")
public MyOtherClass getMyOtherClass() {
return new MyOtherClass(s);
}
}
注意:如果您已经使用
在 Spring 上下文中注册MyClass
@Component
public class MyClass {
...
}
那你就不需要再做一次
@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass) {
return myClass;
}