2009-05-06 10 views
10

Próbuję użyć automatycznej iniekcji zależności za pomocą wiosennej @Configurable adnotation w/@Resource na polach wymagających iniekcji. Wiązało się to z pewną konfiguracją, jak przekazanie spring-agent.jar do mojej maszyny JVM. Pełne szczegóły see here.Dlaczego Spring @Configurable czasami działa, a czasami nie?

Działa ... głównie. Kiedy mój Tomcat się uruchamia, widzę komunikaty inicjujące AspectJ, moje obiekty User User automatycznie otrzymują odwołania do FileService itp.

Problem polega na tym, że czasami tak się nie dzieje. Wydaje się zupełnie przypadkowe; czasami uruchamiam się, a zależności nie są wstrzykiwane, czasami są. Wcześniej miałem problemy z @Transactional będąc na moim użytkowniku, ponieważ stworzyło konflikt, wierzę z proxy. Używam JPA, więc mój użytkownik jest oznaczony @Entity, więc teraz domyślam się, że powoduje to konflikt. Czytałem, że nie możesz automatycznie pośredniczyć w proxy. Aby zrównoważyć konflikt, poszedłem za notatkami, które znalazłem w Internecie, aby wyłączyć Hibernate (moje implanty JPA), wyłączając javassistCGLIB i .

Clues:

  • To wszystko albo nic. Wszystkie moje instancje @Configurable zostały wstrzyknięte lub żadna z nich.
  • Przeładowanie (przywrócenie) obiektu z DB nie wydaje się pomóc; działa albo nie.
  • Zrestartowanie Tomcat dowolną liczbę razy również go nie naprawi. Jedyną rzeczą, która wydaje się rzucić kostką, jest ponowne wprowadzenie. Innymi słowy, jeśli mogę ponownie wdrożyć, może działać.

Jak mogę dowiedzieć się, co dzieje się nie tak? Czy ktoś używa @Configurable z JPA? Dlaczego mój dependencyCheck = true nie wyświetla komunikatu o błędzie, gdy nie są w rzeczywistości wstrzykiwane zależności?

Jednostka

@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

Ja też wystąpiły tego typu problemy z @Configurable i @ Transactional dla długi czas.Myślę, że ma to związek z ładowaniem klas klas przed rozpoczęciem kontekstu wiosny.Zobacz ten wątek: http://forum.springsource.org/showthread.php?t=68406.Sporadyczny charakter ten błąd jest bardzo denerwujący – ghempton

+1

Biorąc pod uwagę wszystkie zmiany na wiosnę, czy istnieje teraz lepsze rozwiązanie tego problemu? – Snekse

Odpowiedz

1

Po iniekcji nie robi Z jakiegoś powodu nie działa żaden kod, aby wykonać test zależności, więc teraz wystąpił błąd.

W przeciwnym razie nie widzę tutaj niczego, co wskazywałoby losową awarię. Czy możesz wyodrębnić uproszczony przykład, aby sprawdzić?

+0

Witam Jörn, dzięki za komentarz.Próbuję uproszczony przykład, kiedy wrócę do domu. pytanie, ponieważ od tej pory przełączyłem się z użycia spring-agent.jar na TomcatInstrumentableClassLoader o mniejszym zakresie, patrz sekcja 6.8.4.6.2. ent. Co dziwne, ta zmiana wydaje się zmniejszać częstotliwość występującego problemu, ale nie rozwiązuje go całkowicie. – rcampbell

+0

Czy istnieje powód, dla którego używasz @Configurable over @Component? –

+0

Zgodnie z dokumentacją oboje zrobią to samo. Używam @Component do iniekcji DI na fasolach zarządzanych przez Spring, podczas gdy ja używam @Config do wtrysku DI na fasolach nie zarządzanych przez Spring. Tak więc, mimo że oboje pracują, używam tych różnych, by wskazać stan sprężyny fasoli. – rcampbell

2

Nie można zauważyć niczego oczywistego, więc wystarczy sugestia - czy próbowałeś używać tkania w czasie kompilacji? Mam nadzieję, że doprowadziłoby to do spójnych wyników w czasie wykonywania, chociaż może to być trochę więcej kłopotów podczas programowania.

+0

Proponowałbym również użycie tkania w czasie kompilacji dla wdrożeń produkcyjnych. Ponadto zapobiega problemom związanym z zapomnieniem przez użytkownika parametru JDK aspektu-tkacza. . . . Tkanie w czasie kompilacji jest idealne do testów integracyjnych. –

1

Wygląda na to, że proces wdrażania jest podejrzany. Czy możesz zrobić wdrożenie, które działa, a następnie skopiować to do katalogu. Następnie wykonaj kolejne wdrożenie, dopóki nie uzyskasz takiego, które nie działa. (W dowolnej kolejności) Następnie w końcu użyj narzędzia takiego, jak poza porównaniem, aby porównać dwie struktury i pliki katalogu wdrażania i sprawdź, czy są jakieś różnice.

Życzymy powodzenia, niczym pozornie przypadkowym problemem, aby zabić trochę wydajności.

+1

To naprawdę dobry pomysł, którego nigdy nie brałem pod uwagę. Wypróbuję to dziś wieczorem. BTW, to zabawne, że zacząłem używać @Configurable, aby ZWIĘKSZYĆ swoją produktywność; przed wykonaniem instrukcji DI w niektórych punktach (np. Factory, Repo itp.) i ścigałem opuszczone obszary, w których obiekt domeny jest tworzony, ale nigdy nie wstrzyknięto. Teraz powiedziałbym, że @Cofig jest +1 dla elegancji, -1 dla wydajności w porównaniu do rozwiązania orig – rcampbell

+0

Tak, jestem teraz w projekcie, w którym używam zestawu nowych technologii. Rzadko zwiększają wydajność, dopóki nie pokonasz garbu. Nawet nie próbowałem zmierzyć się z opisanymi wiosennymi właściwościami. Zbyt wiele nowych rzeczy, a xml działa za każdym razem. –

3

Najpierw muszę powiedzieć, że prawdopodobnie nie jest dobrym pomysłem, aby zasoby, usługi lub inne komponenty bean zostały wstrzyknięte do klas modeli danych jako zależności. Ale to jest kwestia projektu.

Do korzystania z @Configurable użyłem go w przypadkach, gdy obiekty są tworzone z kontekstu spoza kontekstu - jak niestandardowe znaczniki w aplikacjach internetowych, filtrach lub serwletach. Pierwszy sposób, w jaki próbowałem ich użyć, polegał na tasowaniu tak jak Ty. To działało całkiem dobrze, ale miało pewne wady, takie jak wdrażanie hot-code, a debugowanie nie działało.

Zrobiłem również dokładnie problem, który opisujesz, dlatego zdecydowałem się przełączyć z tkania czasu ładowania na czas kompilacji. Dlatego zainstalowałem AJDT plugin w Eclipse i użyłem obsługi aspecjt Spring. To rozwiązało moje problemy.

+0

Dzięki Thomas. Mam kilka wyjaśnień, dlaczego tak to zaprojektowałem: http://stackoverflow.com/questions/694374/how-can-i-resolve-the-conflict-between-lub-coupling-dependency-injection-and-a Zasadniczo sprowadza się to do projektowania opartego na domenie wpływającego na mnie. Moje modele domen były po prostu danymi; reprezentowali głównie rzędy stołów.Po przeczytaniu tej bardzo dobrej książki zdecydowałem się bardziej przejść w kierunku zachowania OOP/danych +, podmioty root odpowiedzialne za swoje podrzędne jednostki itp. Dobrym przykładem tego, gdzie używam tego, jest wstrzyknięcie do fabryki z drutem sprężynowym dla jednostki podrzędnej do swojego rodzica. – rcampbell

+0

co znaczy "bardzo dobra książka"? brzmi interesująco ... –

+0

Książka jest projektowana przez Domain Domain Eric Evans. Dowiedziałem się o tym dzięki rekomendacji Martina Fowlera w "Wzorcach Architektury Aplikacyjnej", która jest kolejną świetną książką. – rcampbell

3

Dla mnie brzmi to jak wystąpienie dobrze znanego wiosną: http://jira.springframework.org/browse/SPR-5401.

Czy to możliwe, że próbujesz użyć Konfigurowalny w kilku kontekstach aplikacji? W takim przypadku tylko jeden z nich będzie podlegał zastrzykowi zależności. Który z nich wygrywa zależy od tego, który kontekst aplikacji jest ostatnim ładowanym.

Rozwiązanie? Brak :-(Nie ma planów naprawienia tego problemu.To jest co najmniej co facet SpringSource powiedział na konferencji JAX w Niemczech w kwietniu