代码之家  ›  专栏  ›  技术社区  ›  João Menighin

Spring@Autowired在一个类的新实例上

  •  6
  • João Menighin  · 技术社区  · 6 年前

    存储库类:

    @Repository
    public class MyRepository {
        // ...
    }
    

    使用存储库类的类:

    public class MyClass extends AbstractClass {
    
        @Autowired
        private MyRepository myRepository;
    
        //...
    }
    

    我知道如果我把我的 MyClass 具有 @Component @Autowired @自动连线 MyRepository 问题是我正处于需要创建新实例的情况 类名 带着沉思。所以呢 我的存储库 从未解析并且始终为空。

    有没有办法使用

    我有一些 AbstractClass . HashMap 这些实现的一部分。基本上:

    {"MyClass", MyClass.class}
    //...
    

    然后我有一个通用的 Controller 映射到url的 /{class}?options=... 使用 {class} @PathVariable 哈希图 在上面和反射中,我能够基于给定的 options

    提前谢谢

    6 回复  |  直到 6 年前
        1
  •  24
  •   Thomas Fritsch    6 年前

    Spring本身提供了一些在对象中进行自动连接的功能 new newInstance() 或者别的什么。

    AutowireCapableBeanFactory 通过Spring的正常依赖注入 @Autowired

    @Autowired
    private  AutowireCapableBeanFactory autowireCapableBeanFactory;
    

    然后你用它 autowireBean(Object) 方法 注入 属性添加到bean中。

    Object myBean = map.get(className).newInstance();
    autowireCapableBeanFactory.autowireBean(myBean);
    

    如果你真的需要上述方法,好好想想。 的javadoc 建议不要在大多数用例中使用此接口:

    BeanFactory的这个子接口并不打算用于普通的应用程序代码:stick to BeanFactory ListableBeanFactory

    其他框架的集成代码可以利用这个接口连接和填充Spring不控制其生命周期的现有bean实例。例如,这对于WebWork操作和Tapestry页面对象特别有用。

        2
  •  4
  •   Rishabh Agarwal    6 年前

    你可以用 Factory Design Pattern

    这可能看起来有点复杂的开始,但我相信你会喜欢它后,你已经实现了。

    步骤:

    1. 在AbstractClass的所有实现中添加@Component。
    2. 将工厂类创建为:

      @Component
      public class MyFactory {
      
          private final Map<String, AbstractClass> impletationMap = new HashMap<>();
      
          @Autowired
          ApplicationContext context;
      
          @PostConstruct
          public void initialize() {
              populateDataMapperMap(context.getBeansOfType(AbstractClass.class).values().iterator());
          }
      
          private void populateDataMapperMap(final Iterator<AbstractClass> classIterator) {
              while (classIterator.hasNext()) {
                  AbstractClass abstractClassImpl = (AbstractClass) classIterator.next();
                  impletationMap.put(abstractClassImpl.getClass().getName(), abstractClassImpl);
      
              }
          }
      }
      

    当这个MyFactory类的Bean初始化后,它将查找AbstractClass类型的所有Bean,并将它们放入HashMap(implementationMap)中。

    现在,您可以从这个工厂获得HashMap,然后根据需要获得实现。当您添加AbstractClass的新实现时,这将非常容易,因为factory会处理它。

        3
  •  3
  •   Alexander Petrov    6 年前

    一种解决方法是不将MyClass绑定到Hashmap来绑定工厂类。我的班级工厂。这样,您将把构造委托给一个具体的工厂,该工厂将执行实例化正确的类和初始化正确的存储库的任务。

    举个例子:

    {"MyClass", MyClassFactory.class}
    

    工厂也可以是组件,然后需要将hashmap绑定到工厂实例,而不是工厂类。但假设它不是一个组件:

    //@Component   this is optional
        public MyClassFactory {
            //@Autowired optional
            ApplicationContext ctx;
    
    
           public MyClass createInstance() {
                MyRepository repo = ctx.getBean("")
                MyClass myclass = new MyClass(repo)
                return myclass;
           }
        }
    

    如果将其标记为组件,那么如果要自动连接ApplicationContext,也可以使用ApplicationContextAware接口。

        4
  •  1
  •   Pankaj Singhal    6 年前

    一种方法是 @Component 在…之上 MyClass .

    实例 属于 而不是 MyClass.class

    注: 您可以获取 类名 从你的 ApplicationContext 在安装阶段。

        5
  •  1
  •   Phenomenal One    6 年前

    @Component    
    public class SomeClass extends AbstractClass {
    
      private static ApplicationContext applicationContext;
    
      public MyClass getMyClass(){
          // Now @Autowired MyRepository will work
          return applicationContext.getBean(MyClass.class);
      }
    
    }
    
        6
  •  0
  •   user10367961 user10367961    6 年前

    @Autowired
    private List<AbstractClass> beans;
    

    如果自动关联列表,Spring不会抱怨重复的定义。