Spring 依赖注入超越基础教程
在我的 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,并且包位于 context:component-scan 中,但是依赖项不会传递,因为 bean 是使用 new 或从缓存创建的,而不是使用 Spring 框架创建的。
我可以使用 appContext.getBean() 创建 Person 对象,但是,这意味着传递 applicationContext 并在应用程序内部使用 getBean() ,这感觉不对。
如何解决问题?
更新:我阅读了文档并尝试了 Ryan Stewart 的建议,并编写了一个小示例项目来尝试。效果很好,谢谢!
https://github.com/stivlo/spring-di
最终,我重构了我原来的项目,在某种程度上我不再需要这个功能,但它是我的武器库中的一个很好的工具。
In my main() method I create a PersonCollection Object using Spring and then I start to load different Persons objects.
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();
In turn PersonCollection.loadById() can load the object from memcached or from 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;
}
So there are two ways to create a Person, the first is deserializing from memcached, the second will call new Person() and assign all data.
Person has two @Autowired properties and is declared as a @Service and the package is in context:component-scan, however the dependencies are not passed, because the bean is created with new or from the cache and not with the Spring framework.
I could use appContext.getBean() to create the Person Object, however, it would mean to pass around the applicationContext and use getBean() inside the application, which doesn't feel right.
How to solve the problem?
UPDATE: I read the documentation and tried the suggestion of Ryan Stewart and wrote a small example project to try it. It works great, thank you!
https://github.com/stivlo/spring-di
Ultimately, I've refactored my original project, in a way that I don't need this feature anymore, but is a good tool to have in my arsenal.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
ApplicationContext.getBean()
。ApplicationContext.getBean()
in your (non-infrastructure) code like the plague.您可能还想研究一个名为
ObjectFactoryCreatingFactoryBean
,这是一种“重用”BeanFactory 功能而不会过度污染的方法您的业务代码无需担心 bean 名称。这样,您的
PersonCollection
实例不需要知道任何 bean 名称,但可以通过以下方式获取新的Person
(注入指定的依赖项):IMO 有一些它可以变得更加方便(例如使用内部 bean 而不是 idref),但这需要一些 Spring-guru 和自定义 XML 命名空间。
You may also want to look into a little oddball utility class called
ObjectFactoryCreatingFactoryBean
, which is a way of "reusing" the capabilities of the BeanFactory without unduly contaminating your business code with worrying about bean names.In this way, your
PersonCollection
instance doesn't need to know any bean names, but can get a freshPerson
(with the specified dependencies injected) via:IMO there are some ways it could be made much more convenient (such as working with an inner bean rather than
idref
) but that would require some Spring-guru and a custom XML namespace.