Spring Dependency Injection за рамками базовых уроков - PullRequest
2 голосов
/ 01 августа 2011

В моем методе main () я создаю объект PersonCollection с использованием Spring, а затем начинаю загружать различные объекты 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, однако зависимости не передаются, поскольку компонент создается с новым или из кэша, а не с Spring фреймворк.

Я мог бы использовать appContext.getBean () для создания объекта Person, однако это означало бы обойти applicationContext и использовать getBean () внутри приложения, что выглядит неправильно.

Как решить проблему?

ОБНОВЛЕНИЕ : Я прочитал документацию и попробовал предложение Райана Стюарта и написал небольшой пример проекта, чтобы попробовать его. Отлично работает, спасибо!

https://github.com/stivlo/spring-di

В конечном итоге я реорганизовал свой оригинальный проект таким образом, что эта функция мне больше не нужна, но это хороший инструмент для моего арсенала.

Ответы [ 2 ]

5 голосов
/ 01 августа 2011
  1. Да, избегайте ApplicationContext.getBean() в своем (не инфраструктурном) коде, таком как чума.
  2. Вариант 1: не связывайте автоматически POJO-подобные классы.Вытащите это в «сервисный» объект, который тесно связан с Человеком.Это более или менее современный мейнстримный подход, и я надеюсь, что он уйдет, потому что он становится беспорядочным.
  3. Вариант второй: Использование AspectJ с использованием аннотации @Configurable , чтобы сделать Person автоматически желаемым независимогде он создан.Мне действительно нравится этот вариант, хотя я еще не использовал его в производственном проекте.
1 голос
/ 03 августа 2011

Вы также можете захотеть взглянуть на небольшой странный класс утилит под названием ObjectFactoryCreatingFactoryBean, который является способом «повторного использования» возможностей BeanFactory без чрезмерного заражения вашего бизнес-кода опасениями по поводу имен бинов..

<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 не нужно знать имена бинов, но он может получить новый Person (с введенными указанными зависимостями) через:

Person p = (Person) this.personMaker.getObject();

IMO Есть несколько способов сделать это гораздо более удобным (например, работать с внутренним компонентом, а не idref), но для этого потребуются некоторый Spring-гуру и пользовательское пространство имен XML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...