簡體   English   中英

Spring @Autowired在一個類新實例上

[英]Spring @Autowired on a class new instance

我對Spring不太熟悉,我有以下情況:

存儲庫類:

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

使用存儲庫類的類:

public class MyClass extends AbstractClass {

    @Autowired
    private MyRepository myRepository;

    //...
}

我知道如果我使用@Component注釋我的MyClass並將其與@Autowired一起使用,那么@Autowired MyRepository就可以解決了。 問題是我需要使用反射創建MyClass新實例。 所以MyRepository永遠不會被解析,並且一直都是null。

在這種情況下有沒有辦法使用@Autowired

更好地解釋我的情況:我有一些AbstractClass實現。 在我的應用程序的設置階段,我創建了這些實現的HashMap 基本上:

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

然后我有一個通用的Controller映射到url /{class}?options=...使用{class} @PathVariable ,上面的HashMap和反射我能夠根據給定的options創建一個類的實例(這部分很重要)。 你們認為有更好的方法嗎?

提前致謝

Spring本身提供了一些功能,可以在newnewInstance()或其他任何東西創建的對象中進行自動連接。

要使用它,您需要一個AutowireCapableBeanFactory ,您可以通過Spring使用@Autowired正常的依賴注入。

@Autowired
private  AutowireCapableBeanFactory autowireCapableBeanFactory;

然后使用其autowireBean(Object)方法將@Autowired屬性注入到bean中。

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

設計說明:

如果你真的需要上面的方法,請好好想想。 AutowireCapableBeanFactory的javadoc建議不要在大多數用例中使用此接口:

BeanFactory的這個子接口並不適用於普通的應用程序代碼:對於典型的用例,堅持使用BeanFactoryListableBeanFactory

其他框架的集成代碼可以利用此接口來連接和填充Spring無法控制其生命周期的現有Bean實例。 例如,這對WebWork Actions和Tapestry Page對象特別有用。

一種解決方法是將MyClass綁定到Hashmap以綁定Factory類。 MyClassFactory。 通過這種方式,您可以將構造委派給具體工廠,該工廠將完成實例化正確的類並初始化正確的存儲庫。

這是一個例子:

{"MyClass", MyClassFactory.class}

工廠也可以是Component,然后您需要將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;
       }
    }

如果將其標記為組件,則還可以使用ApplicationContextAware接口(如果要自動裝配ApplicationContext)。

您可以在此處使用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的新實現時,它將非常容易,因為工廠將負責處理它。

一種方法是在MyClass之上聲明@Component

然后,在設置階段,您可以在HashMap中傳遞MyClass實例而不是MyClass.class本身。 不需要通過反射創建實例。

注意:您可以在設置階段從ApplicationContext中獲取MyClass的實例。

試試這個

@Component    
public class SomeClass extends AbstractClass {

  private static ApplicationContext applicationContext;

  public MyClass getMyClass(){
      // Now @Autowired MyRepository will work
      return applicationContext.getBean(MyClass.class);
  }

}

是的,您可以使用@Component注釋所有AbstractClass實現bean並使用下一個聲明

@Autowired
private List<AbstractClass> beans;

然后,您可以將其轉換為@PostConstruct方法中的Map。

如果您自動加載列表,Spring不會抱怨重復的定義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM