在我的main()方法中,我使用Spring创建一个PersonCollection对象,然后我开始加载不同的Persons对象。
BeanFactory appContext = new ClassPathXmlApplicationContext("cp-beans.xml");
PersonCollection pc = appContext.getBean(PersonCollection.class);
Person aPerson = pc.loadById(1);
aPerson.doSomething();
aPerson.loadById(1067);
aPerson.doSomething();
反过来,PersonCollection.loadById()可以从memcached或Amazon SimpleDB加载对象:
public Person loadById(int id) throws ConnectException, NoSuchElementException {
String memCacheKey = "Person-" + id;
Person aPerson = (Person) cache.get(memCacheKey);
if (aPerson != null) {
return aPerson; //cache hit
}
aPerson = loadByIdFromSdb(id); //cache miss, read it from SimpleDB
cache.set(memCacheKey, aPerson);
return aPerson;
}
因此有两种创建Person的方法,第一种是从memcached反序列化,第二种是调用new Person()并分配所有数据。
Person有两个@Autowired属性并被声明为@Service并且包在上下文中:component-scan,但是不传递依赖关系,因为bean是用new创建的,或者是从缓存而不是Spring创建的框架。
我可以使用appContext.getBean()创建Person对象,但是,这意味着传递applicationContext并在应用程序中使用getBean(),这感觉不对。
如何解决问题?
更新:我阅读了文档并尝试了Ryan Stewart的建议并编写了一个小示例项目来尝试它。它很棒,谢谢!
https://github.com/stivlo/spring-di
最终,我已经重构了我原来的项目,我不再需要这个功能了,但它是我的武器库中的一个很好的工具。
答案 0 :(得分:5)
ApplicationContext.getBean()
,例如瘟疫。答案 1 :(得分:1)
您可能还想查看一个名为ObjectFactoryCreatingFactoryBean
的奇怪的实用工具类,这是一种“重用”BeanFactory功能的方式,而不会因为担心bean名称而过度污染您的业务代码。
<beans>
<bean id="PersonCollection " class="com.example.PersonCollection">
<property name="personMaker" ref="PersonMaker"/>
</bean>
<bean id="personPrototype" class="com.example.Person" scope="prototype">
<!-- Things to inject onto a newly-made person -->
</bean>
<bean id="PersonMaker" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName"><idref local="personPrototype"/></property>
</bean>
</beans>
通过这种方式,您的PersonCollection
实例不需要知道任何bean名称,但可以通过以下方式获取新的Person
(注入指定的依赖项):
Person p = (Person) this.personMaker.getObject();
IMO有一些方法可以使它更方便(例如使用内部bean而不是idref
),但这需要一些Spring-guru和一个自定义XML命名空间。