【问题标题】:How to make @autowire work in spring when creating instance manually手动创建实例时如何使@autowire在春季工作
【发布时间】:2018-01-24 09:04:13
【问题描述】:


我有一个 java 接口,说 ITest 由两个类 Class1 和 Class2 实现。现在我有一个工厂类,我用它来决定返回哪个实现。喜欢

if(something)
    return new Class1()
else
   return new Class2()

问题是我在 Class1 中有自动装配字段,它没有被实例化,但是相同的自动装配在通过自动装配实例化的其他类中工作。
这是 Class1 的代码

@Componene
public Class1 implements ITest{
  @Autowired
  private SomeClass obj;
}

不知道如何解决这个问题。由于 SomeClass 的自动装配在其他类中工作正常。

【问题讨论】:

  • 如果你自己实例化它们,你不能自动装配对象
  • 我该如何解决这个问题?我的工厂类需要根据特定条件返回实例。所以我必须手动实例化
  • 您可以做的是,在您的 Spring 配置中,创建与您不同的 Classes 相对应的 @Bean,您将通过 setter 或构造函数在其中注入 SomeClass 对象。这样,您不会在工厂中制造新产品,而是在工厂中自动连接您的 Classes。不过,我有点不鼓励这样做,因为这不是干净的代码。
  • 使用 spring 时做new 是犯罪行为:)。说了这么多,试试Prototypebean

标签: java spring autowired


【解决方案1】:

在您的工厂类中注入 applicationContext 并将其用于创建 bean:

@Autowired private ApplicationContext applicationContext;
......
......
         if(something){
            return applicationContext.getBean("com.xyz.Class1");
         }
......
......

或者您可以在 Class1 和 Class2 之上使用@Configurable。这需要启用 AspectJ 编织。然后,当您使用 new 时,Spring 会神奇地创建 bean。

【讨论】:

    【解决方案2】:

    这很大程度上取决于您到底需要什么,但您可以:

    1. 将 factory 返回的对象定义为原型作用域并将其注入到单例中,更多详细信息请参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes-sing-prot-interaction

    那么整个魔法都是由 Spring 完成的

    1. 如果你只是想在两个不同的无状态实现之间切换,你可以将它们都注入工厂并返回一个现有的 bean

      @Compoment class Factory { 
      
        @Autowired 
        Class1 class1Instance;
      
        @Autowired 
        Class2 classInstance;
        ...
        if(something)
          return class1Instance;
        else
         return class2Instance;
        ...
      }
      

      }

    但请确保两个注入的类都没有状态。

    1. 使工厂由 Spring 管理,两个类都不受 Spring 管理并手动注入依赖项:

      public Class1 implements ITest{
      
        private SomeClass obj;
      
        public Class1(SomeClass obj) {
              this.obj=obj;}
      }
      

    在工厂中:

      @Autowired
      private SomeClass obj;
       ...
       if(something)
         return new Class1(obj);
       else
        return new Class2(obj);
    

    乍一看看起来很奇怪,通过这种方式你可以例如单独的域和应用程序/基础架构部分。

    【讨论】:

      【解决方案3】:

      您可以使用带有@SpringBootApplication 或@Configuration 注释的主配置类。

      例子:

      @SpringBootApplication
      public class YourApp {
      
         public static void main(String[] args) {
             SpringApplication.run(YourApp.class, args);
         }
      
         @Autowired
         private CsvBeanRepository repo;
      
         @Bean
         public InterfaceSome some() {
             if(something) {
                 return new Some(repo);
             } else {
                 return new Some2(repo);
             }
         }
      }
      

      在@SpringBootApplication 类或@Configuration 类中,您可以正常地@Autowire 您的类并将它们用作工厂的参数。

      【讨论】:

        【解决方案4】:

        我建议在这种情况下使用@value 注释。

        例子

        我的班级{

        Object getObjectFromFactory()
        {
          if(something)
            return new Class1()
         else
            return new Class2()
        }
        

        }

        那么你可以像下面这样使用它

        @Value("#{MyClass.getObjectFromFactory}")

        私有对象 myObject;

        【讨论】:

          猜你喜欢
          • 2017-06-04
          • 2015-11-21
          • 1970-01-01
          • 1970-01-01
          • 2021-07-15
          • 2012-02-17
          • 2014-03-27
          • 1970-01-01
          • 2013-12-22
          相关资源
          最近更新 更多