代码之家  ›  专栏  ›  技术社区  ›  user6219476

bean类能否实例化内部的另一个类,我们是否应该/如何避免它?

  •  1
  • user6219476  · 技术社区  · 6 年前

    假设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 a 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;
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Kirill Simonov    6 年前

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

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

    它是安全的,但不是依赖注入: MyOtherClass公司 不是由Spring管理的,因此您无法使用 @Autowired 或者将其他spring托管类注入 MyOtherClass公司 . 而且,正如Andrew所提到的,不可能嘲笑 MyOtherClass公司 .

    如果正在注册 MyOtherClass公司 由于Spring上下文中的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;
    }
    
        2
  •  1
  •   Andrew S    6 年前

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

    并将该类配置为Springbean,但没有 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公司 就像豆子一样。