2009-05-06 4 views
10

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

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

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

Улики:

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

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

Сущность

@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" /> 

... 
+1

Я тоже сталкивался с этими проблемами при использовании @Configurable и @Transactional для долгое время. Я думаю, что это связано с загрузкой классов загрузкой классов до инициализации контекста весны. См. эту тему: http://forum.springsource.org/showthread.php?t=68406. Спорадический характер эта ошибка очень раздражает. – ghempton

+1

Учитывая все изменения в Spring, есть ли теперь лучшее решение этой проблемы? – Snekse

ответ

1

Когда инъекции МЭ sn't work, по какой-то причине, нет никакого способа для кода делать проверку зависимостей, поэтому теперь возникает ошибка.

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

+0

Привет, Jörn, спасибо за комментарий. Я попробую упрощенный пример, когда вернусь домой. Мне нужно обновить эту вопрос, потому что с тех пор я переключился с использования spring-agent.jar на объект TomcatInstrumentableClassLoader с меньшим охватом, см. раздел 6.8.4.6.2. Tomcat of the spring reference docum Ent. Как ни странно, это изменение, как представляется, снижает частоту возникающей проблемы, но не фиксирует ее полностью. – rcampbell

+0

Есть ли причина, по которой вы используете @Configurable over @Component? –

+0

Согласно документации, они оба выполнили бы то же самое здесь. Я использую @Component для инъекции DI на управляемых Spring бобах, в то время как я использую @Config для инъекции DI на управляемых не-Spring компонентах. Поэтому, несмотря на то, что они оба работают, я использую разные, чтобы намекнуть о статусе Spring в bean-компоненте. – rcampbell

2

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

+0

Я бы также предложил использовать компиляцию во времени для развертывания производства. Также предотвращает проблемы, связанные с тем, что кто-то забывает установить параметр JDK для аспект-j. , , , компиляция во времени подходит для интеграционных тестов. –

1

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

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

+1

Это действительно хорошая идея, которую я никогда не рассматривал. Я попробую это сегодня вечером. Кстати, смешно, что я начал использовать @Configurable, чтобы УВЕЛИЧИТЬ свою производительность; прежде чем я делал ручной DI в определенных точках (например, Factory, Repo и т. д.), и я преследовал пропущенные области, где объект домена был создан, но не был введен. Прямо сейчас я бы сказал, что @Cofig +1 для элегантности, -1 для производительности по сравнению с решением orig – rcampbell

+0

Да, я сейчас в проекте, где я использую набор новых технологий. Они редко улучшают производительность, пока вы не перевернете ее над горбом. Я даже не пробовал смотреть на аннотированные свойства весны. Слишком много нового, и xml работает каждый раз. –

3

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

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

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

+0

Спасибо Томас. У меня есть некоторое объяснение, почему я сконструировал его следующим образом: http://stackoverflow.com/questions/694374/how-can-i-resolve-the-conflict-between-loose-coupling-dependency-injection-and-a В основном это зависит от того, как дизайн, управляемый доменом, влияет на меня. Мои модели домена были просто данными; они в основном представляли строки таблицы.Прочитав эту очень хорошую книгу, я решил больше двигаться в направлении поведения ООП/данных +, корневых сущностей, несущих ответственность за их дочерние сущности, и т. Д. Хорошим примером того, где я использую это, является внедрение Spring-wired Factory для дочернего объекта в его родителя. – rcampbell

+0

, о котором вы говорите «очень хорошая книга»? звучит интересно ... –

+0

Книга - проект, управляемый доменом Эрика Эванса. Я узнал об этом по рекомендации Мартина Фаулера в «Шаблонах архитектуры корпоративных приложений», которая является еще одной действительно большой книгой. – rcampbell

3

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

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

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