1

假设 bean 在这里注册。

@Configuration
public class configuration{

    @Bean(name = "MyClass")
    public MyClass getMyClass(@Value("avalue") final String s){
        return new MyClass(s);
        }
    }
}

并且该类在内部实例化了另一个类,如下所示(两者都不需要注释?)

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;
    }
}
4

2 回答 2

1

如果您不想公开您MyOtherClass的实例并控制其创建实例,您可以使用第一种方法:

...
public MyClass(String s) {
    this.myOtherClass = new MyOtherClass(s);
}

它是安全的,但它不是依赖注入:MyOtherClass不是由 Spring 管理的,因此您将无法使用其他 bean 将其@Autowired注入或将其他 Spring 托管类注入MyOtherClass. 此外,正如 Andrew 所提到的,模拟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);
    }
}

注意:如果您已经MyClass在 Spring 上下文中使用

@Component
public class MyClass {
    ...
}

那么你不需要再做一次

@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass) {
    return myClass;
}
于 2018-02-14T21:22:20.797 回答
1

在 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;
    }
}

并将类配置为 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。

于 2018-02-14T19:44:49.333 回答