![](/img/trans.png)
[英]Difference between autowired and using new keyword on autowired class in spring boot?
[英]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本身提供了一些功能,可以在new
或newInstance()
或其他任何東西創建的對象中進行自動連接。
要使用它,您需要一個AutowireCapableBeanFactory
,您可以通過Spring使用@Autowired
正常的依賴注入。
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
然后使用其autowireBean(Object)
方法將@Autowired
屬性注入到bean中。
Object myBean = map.get(className).newInstance();
autowireCapableBeanFactory.autowireBean(myBean);
設計說明:
如果你真的需要上面的方法,請好好想想。 AutowireCapableBeanFactory
的javadoc建議不要在大多數用例中使用此接口:
BeanFactory的這個子接口並不適用於普通的應用程序代碼:對於典型的用例,堅持使用
BeanFactory
或ListableBeanFactory
。其他框架的集成代碼可以利用此接口來連接和填充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 。
這可能在開始時看起來有點復雜,但我相信在你實現它之后你會喜歡它。
腳步:
創建一個工廠類:
@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.