@Resource vs. @Autowired


380

Której adnotacji @Resource ( jsr250 ) lub @Autowired (specyficzny dla wiosny) należy użyć w DI?

Z powodzeniem korzystałem zarówno w przeszłości, jak @Resource(name="blah")i@Autowired @Qualifier("blah")

Instynktownie @Resourcetrzymam się tagu, ponieważ został ratyfikowany przez ludzi jsr.
Czy ktoś ma na to mocne przemyślenia?


Do Twojej wiadomości - usunąłem „aktualizację”, powinna była zostać zadana jako osobne pytanie. Zgodnie z odrzuconym komentarzem: „Ta zmiana odbiega od pierwotnych założeń posta. Nawet zmiany, które muszą wprowadzić drastyczne zmiany, powinny dążyć do zachowania celów właściciela posta”
mlo55

Odpowiedzi:


194

Wiosną przed wersją 3.0 nie ma znaczenia, który z nich.

Wiosną 3.0 dostępna jest obsługa standardowej adnotacji ( JSR-330 ) @javax.inject.Inject- użyj jej z kombinacją @Qualifier. Pamiętaj, że wiosna obsługuje teraz także @javax.inject.Qualifiermeta-adnotację:

@Qualifier
@Retention(RUNTIME)
public @interface YourQualifier {}

Więc możesz mieć

<bean class="com.pkg.SomeBean">
   <qualifier type="YourQualifier"/>
</bean>

lub

@YourQualifier
@Component
public class SomeBean implements Foo { .. }

I wtedy:

@Inject @YourQualifier private Foo foo;

Dzięki temu rzadziej używane są nazwy ciągów, które mogą być błędnie napisane i trudniejsze do utrzymania.


Jeśli chodzi o pierwotne pytanie: oba, bez określania atrybutów adnotacji, wykonaj wstrzyknięcie według typu. Różnica polega na:

  • @Resource pozwala określić nazwę wstrzykniętej fasoli
  • @Autowired pozwala oznaczyć go jako nieobowiązkowy.

To może wyglądać jak głupie pytanie, ale kiedy używasz tego stylu wstrzykiwania, potrzebujesz publicznego setera foolub konstruktora SomeBeanz Fooparam?
Snekse

@Snekse - Mam moją odpowiedź: stackoverflow.com/questions/3536674/…
Snekse

nie. Nie potrzebujesz tego. Tylko pole. (Wiosna zapełnia ją odbiciem)
Bozho

@Bozho Ta odpowiedź w rzeczywistości nie pokazuje różnicy między, @Resourcea @Autowiredfaktyczna odpowiedź to ta opublikowana przez @Ichthyo, myślę, że należy ją zaktualizować.
Boris Treukhov

1
tak. W rzeczywistości czasami odpowiadam na pytania, zapewniając lepszą alternatywę dla tego podejścia. Ale poniżej zamieściłem odpowiedź na pierwotne pytanie
Bozho

508

Zarówno @Autowired(lub @Inject) i @Resourcedziałają równie dobrze. Ale istnieje różnica pojęciowa lub różnica w znaczeniu

  • @Resourceoznacza zdobądź znany zasób według nazwy . Nazwa jest wyodrębniana z nazwy ustawiającego z adnotacjami lub pola albo z nazwy-parametru.
  • @Injectlub @Autowiredspróbuj podłączyć odpowiedni inny komponent według rodzaju .

Zasadniczo są to dwa zupełnie różne pojęcia. Niestety, wiosenna implementacja @Resourcema wbudowaną funkcję zastępczą, która uruchamia się, gdy zawiodą rozpoznawanie nazw. W takim przypadku sprowadza się do @Autowiredrodzaju rozdzielczości według rodzaju. Chociaż ta awaria jest wygodna, IMHO powoduje wiele zamieszania, ponieważ ludzie nie zdają sobie sprawy z różnicy pojęciowej i zwykle używają @Resourcedo automatycznego zasilania opartego na typach.


81
Tak, to powinna być zaakceptowana odpowiedź. Na przykład, jeśli masz @Resourcepole z adnotacją, a nazwa pola pasuje do identyfikatora fasoli w pojemniku, to Spring rzuci, org.springframework.beans.factory.BeanNotOfRequiredTypeExceptionjeśli ich typy się różnią - dzieje się tak, ponieważ fasola jest najpierw dopasowywana według nazwy w @Resourceadnotacji, a nie według typu. Ale jeśli nazwa właściwości nie zgadza się z nazwą fasoli, to Spring podłączy je według typu.
Boris Treukhov

Możesz odnieść się do drugiego postu, który mówi różnicę między tymi dwoma, gdy próbujesz użyć prostej mapy. stackoverflow.com/questions/13913752/…
Anver Sadhat

4
+1 za faktyczne udzielenie odpowiedzi na pytanie, a nie po prostu zalecenie zupełnie innej „najlepszej praktyki”, tak jak to robi akceptowana odpowiedź. Znalazłem również ten post na blogu, który pokazuje wyniki kilku typowych scenariuszy ze wszystkimi trzema stylami adnotacji, pomocny: blogs.sourceallies.com/2011/08/…
Jules

1
Dla czytelnika znajdziesz streszczenie artykułu wskazanego przez @Jules tutaj: stackoverflow.com/a/23887596/363573
Stephan

3
Jedna z implikacji tego: kiedy chcesz wstrzyknąć fasolę Map / List, @Autowirenie może i nie będzie działać. W takim przypadku będziesz musiał użyć @Resource.
Ricardo van den Broek

76

Podstawowa różnica polega na tym, że @Autowiredjest to adnotacja wiosenna. Natomiast @Resourcejest określony przez JSR-250, jak sam zauważyłeś. Tak więc ten drugi jest częścią Javy, podczas gdy ten pierwszy jest związany ze wiosną.

Dlatego masz rację, sugerując to w pewnym sensie. Znalazłem ludzie korzystać @Autowiredz @Qualifierponieważ jest bardziej wydajny. Przejście z jednego frameworka do innego jest uważane za bardzo mało prawdopodobne, jeśli nie mit, szczególnie w przypadku wiosny.


7
+1, bo @Autowiredz @Qualifiernaprawdę jest mocniejszy niż JSR standardowym @Resourceadnotacji (myślę opcjonalnych zależności na przykład z @Autowired(required=false). Nie można tego zrobić z @Resource)
Stefan Haberl

70

Chciałbym podkreślić jeden komentarz @Jules dotyczący tej odpowiedzi na to pytanie. Komentarz zawiera użyteczny link: Spring Injection z @Resource, @Autowired i @Inject . Zachęcam do przeczytania go w całości, jednak oto krótkie podsumowanie jego przydatności:

Jak adnotacje wybierają właściwą implementację?

@Autowired i @Inject

  1. Dopasowuje według typu
  2. Ograniczenia według kwalifikatorów
  3. Dopasowania według nazwy

@Resource

  1. Dopasowania według nazwy
  2. Dopasowuje według typu
  3. Ograniczenia według kwalifikatorów (ignorowane, jeśli dopasowanie zostanie znalezione według nazwy)

Których adnotacji (lub kombinacji) należy użyć do wstrzyknięcia fasoli?

  1. Jawnie nazwij swój komponent [@Component („beanName”)]

  2. Użyj @Resourcez nameatrybutem [@Resource (name = "beanName")]

Dlaczego nie powinienem używać @Qualifier?

Unikaj @Qualifieradnotacji, chyba że chcesz utworzyć listę podobnych ziaren. Na przykład możesz chcieć oznaczyć zestaw reguł określoną @Qualifieradnotacją. Takie podejście ułatwia wstrzyknięcie grupy klas reguł do listy, której można użyć do przetwarzania danych.

Czy wstrzykiwanie fasoli spowalnia mój program?

Skanuj określone pakiety w poszukiwaniu komponentów [context:component-scan base-package="com.sourceallies.person"]. Doprowadzi to do większej liczby component-scankonfiguracji, ale zmniejsza ryzyko dodania niepotrzebnych komponentów do kontekstu Spring.


Odniesienie: Spring Injection z @Resource, @Autowired i @Inject


39

Oto, co otrzymałem z Podręcznika referencyjnego Spring 3.0.x : -

Wskazówka

Jeśli zamierzasz wyrazić iniekcję opartą na adnotacjach według nazwy, nie używaj przede wszystkim @Autowired, nawet jeśli technicznie jest w stanie odwoływać się do nazwy fasoli za pomocą wartości @Qualifier. Zamiast tego użyj adnotacji @Resource JSR-250, która jest semantycznie zdefiniowana, aby zidentyfikować określony komponent docelowy za pomocą jego unikalnej nazwy, przy czym zadeklarowany typ nie ma znaczenia dla procesu dopasowywania.

Szczególną konsekwencją tej różnicy semantycznej jest to, że fasoli, które same są zdefiniowane jako typ kolekcji lub mapy, nie można wstrzykiwać przez @Autowired, ponieważ dopasowanie typu nie ma do nich odpowiedniego zastosowania. Użyj @Resource dla takich ziaren, odnosząc się do konkretnej kolekcji lub ziaren mapy pod unikalną nazwą.

@Autowired ma zastosowanie do pól, konstruktorów i metod wieloparametrowych, pozwalając na zawężanie poprzez adnotacje kwalifikatora na poziomie parametru. Natomiast @Resource jest obsługiwany tylko dla metod ustawiania pól i właściwości komponentu bean za pomocą jednego argumentu. W związku z tym trzymaj się kwalifikatorów, jeśli celem iniekcji jest konstruktor lub metoda z wieloma argumentami.


Aktualna wersja znajduje się w docs.spring.io/spring/docs/current/spring-framework-reference/… (wskazówka została zaktualizowana)
Lu55,

27

@Autowired + @Qualifier będzie działać tylko ze sprężyną DI, jeśli chcesz użyć innego DI w przyszłości @Resource jest dobrą opcją.

Inną różnicą, którą uznałem za bardzo znaczącą, jest to, że @Qualifier nie obsługuje dynamicznego okablowania komponentu bean, ponieważ @Qualifier nie obsługuje symboli zastępczych, podczas gdy @Resource robi to bardzo dobrze.

Na przykład: jeśli masz interfejs z wieloma takimi implementacjami

interface parent {

}
@Service("actualService")
class ActualService implements parent{

}
@Service("stubbedService")
class SubbedService implements parent{

}

z @Autowired & @Qualifier musisz ustawić konkretną implementację potomną, taką jak

@Autowired
@Qualifier("actualService") or 
@Qualifier("stubbedService") 
Parent object;

który nie zapewnia symbolu zastępczego podczas korzystania z @Resource, można umieścić symbol zastępczy i użyć pliku właściwości do wstrzyknięcia określonej implementacji podrzędnej, takiej jak

@Resource(name="${service.name}")
Parent object;  

gdzie nazwa.usługi jest ustawiona w pliku właściwości jako

#service.name=actualService
 service.name=stubbedService

Mam nadzieję, że ktoś komuś pomoże :)


16

Oba są równie dobre. Zaletą korzystania z Resource jest w przyszłości, jeśli chcesz użyć innej struktury DI niż wiosna, zmiany w kodzie będą znacznie prostsze. Używając Autowired, twój kod jest ściśle powiązany ze sprężynami DI.


17
Nigdy się nie zdarzy. I nawet gdyby tak było - wykonanie wyszukiwania / zamiany nazw adnotacji będzie najmniejszym z twoich problemów.
Daniel Alexiuc

13

Kiedy krytycznie przeanalizujesz z klas podstawowych tych dwóch adnotacji, zauważysz następujące różnice.

@Autowiredużywa AutowiredAnnotationBeanPostProcessor do wstrzykiwania zależności.
@ResourcewykorzystujeCommonAnnotationBeanPostProcessor do wstrzykiwania zależności.

Mimo że używają różnych klas postprocesorów, wszystkie zachowują się prawie identycznie. Różnice krytycznie leżą w ścieżkach ich wykonania, które podkreśliłem poniżej.

@Autowired / @Inject

1. Dopasowania według typu 2.
Ograniczenia według kwalifikatorów
3. Dopasowania według nazwy

@Resource

1. Dopasowania według nazwy 2.
Dopasowania według typu
3. Ograniczenia według kwalifikatorów (ignorowane, jeśli dopasowanie zostanie znalezione według nazwy)


6

Z @Resource możliwości samodzielnego wstrzykiwania fasoli może być potrzebna do uruchomienia całej dodatkowej logiki dodanej przez procesory fasoli, takie jak transakcyjne lub związane z bezpieczeństwem.

Z Spring 4.3+ @Autowiredjest również w stanie to zrobić.


2

@Resourcejest często używany przez obiekty wysokiego poziomu, zdefiniowane przez JNDI. @Autowiredlub @Injectbędą używane przez bardziej popularne ziarna.

O ile mi wiadomo, nie jest to specyfikacja ani nawet konwencja. Jest to bardziej logiczny sposób, w jaki standardowy kod użyje tych adnotacji.


0

Uwaga: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContexti SpringBeanAutowiringSupport.processInjectionBasedOnServletContext NIE DZIAŁA z @Resource adnotacjami. Istnieją więc różnice.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.