Почему SpringConfigurable иногда работает, а иногда нет? - PullRequest
10 голосов
/ 06 мая 2009

Я пытаюсь использовать автоматическое внедрение зависимостей через аннотацию Spring @Configurable w / @Resource для полей, требующих внедрения. Это включало некоторую настройку, такую ​​как передача spring-agent.jar моей JVM. Для полной информации см. Здесь .

Это работает ... в основном. Когда мой Tomcat загружается, я вижу сообщения инициализации AspectJ, мои объекты User автоматически получают ссылки FileService и т. Д.

Проблема в том, что иногда этого просто не происходит. Это кажется совершенно случайным; иногда я загружаюсь и зависимости не вводятся, иногда они есть. Раньше у меня были проблемы с тем, что @Transactional был на моем Пользователе, потому что это создало конфликт, я полагаю, с прокси. Я использую JPA, поэтому мой пользователь помечен @Entity, поэтому сейчас я думаю, что это создает конфликт. Я читал, что вы не можете автоматически прокси прокси. Чтобы компенсировать конфликт, я следил за некоторыми заметками, которые я нашел в Интернете об исключении CGLIB и javassist , которые использует Hibernate (мой JPA).

Подсказки:

  • Это все или ничего. Все мои экземпляры @Configurable были введены или ни один из них.
  • Перезагрузка (восстановление) сущности из БД, похоже, не помогает; это либо работает, либо нет.
  • Перезагрузка Tomcat в любое время также даже не исправит это. Единственное, что снова бросает кости - это повторное развертывание. Другими словами, если я перераспределу, это может сработать.

Как я могу понять, что происходит не так? Кто-нибудь использует @Configurable с JPA? Почему мой dependencyCheck = true не выдает ошибку, когда зависимости фактически не вводятся?

Entity

@Entity
@Configurable(dependencyCheck = true)
@NamedQueries( { @NamedQuery(name = "User.findAll", query = "SELECT user FROM User user"),
    @NamedQuery(name = "User.findByEmail", query = "SELECT user FROM User user WHERE user.email = :email") })
public abstract class User extends BaseModel {

private static final long serialVersionUID = 7881431079061750040L;

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;

@Column(unique = true, nullable = false)
private String email;

@Basic(optional = false)
private String password;

@Resource
private transient UserEmailer userEmailer;

@Resource
private transient FileService fileService;

...

aop.xml

<!DOCTYPE aspectj PUBLIC
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver options="-verbose">
        <include within="com.myapp.domain..*" />
        <exclude within="*..*CGLIB*" />
        <exclude within="*..*javassist*" />
    </weaver>
    <aspects>
        <aspect name="org.springframework.beans.factory.aspectj.AbstractInterfaceDrivenDependencyInjectionAspect" />
    </aspects>
</aspectj>

applicationContext.xml

...

<context:spring-configured />

<context:load-time-weaver />

<context:component-scan base-package="com.myapp" />

...

Ответы [ 5 ]

3 голосов
/ 26 мая 2009

Для меня это звучит как появление известной ошибки весной: http://jira.springframework.org/browse/SPR-5401.

Может ли быть так, что вы пытаетесь использовать Configurable в нескольких контекстах приложения? В этом случае только один из них будет подвержен внедрению зависимости. Какой из них выиграет, зависит от того, какой контекст приложения загружается последним.

Решение? Нет :-( Нет планов по решению этой проблемы. По крайней мере, так сказал парень из SpringSource на конференции JAX в Германии в апреле.

3 голосов
/ 20 мая 2009

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

Для использования @Configurable я использовал его в тех случаях, когда объекты создаются вне контекста Spring - как пользовательские теги в веб-приложениях, фильтрах или сервлетах. Первый способ, которым я пытался использовать их, был ткачество времени загрузки, как вы делаете. Это работало довольно хорошо, но у него были некоторые недостатки, такие как горячее развертывание кода, тогда как отладка больше не работала.

У меня также возникла именно та проблема, которую вы описываете, и поэтому я решил переключиться со времени загрузки на время компиляции. Для этого я установил плагин AJDT в Eclipse и использовал поддержку Spring в aspecjt. Это решило мои проблемы.

2 голосов
/ 18 мая 2009

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

1 голос
/ 19 мая 2009

Похоже, ваш процесс развертывания подозрительный. Можете ли вы сделать развертывание, которое работает, а затем скопировать его в каталог. Затем выполните другое развертывание, пока не получите тот, который не работает. (В любом порядке) Затем, наконец, используйте инструмент, подобный «вне всякого сравнения», чтобы сравнить две структуры и файлы каталогов развертывания и посмотреть, есть ли различия.

Удачи, ничего похожего на случайную проблему, которая убивает некоторую производительность.

1 голос
/ 14 мая 2009

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

В противном случае я не вижу здесь ничего, что указывало бы на случайный сбой. Можете ли вы извлечь упрощенный пример для проверки?

...