Understanding Spring @ Autowired usage
[[3]] czytam spring 3.0.x reference documentation to understand Spring Autowired adnotation:
Nie jestem w stanie zrozumieć poniższych przykładów. Czy musimy zrobić coś w XML, aby to działało?
Przykład 1
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
Przykład 2
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
Jak dwie klasy mogą być autowirowane implementując ten sam interfejs i używając tej samej klasy?
Przykład:
class Red implements Color
class Blue implements Color
class myMainClass{
@Autowired
private Color color;
draw(){
color.design();
}
}
Która metoda projektowa będzie być wezwanym? Jak upewnić się, że metoda projektowania klasy Red zostanie wywołana, a nie Niebieska?
4 answers
TL; DR
Adnotacja @Autowired oszczędza Ci potrzeby samodzielnego wykonywania okablowania w pliku XML (lub w inny sposób) i po prostu znajduje Dla ciebie to, co trzeba wstrzyknąć gdzie, i robi to za Ciebie.
Pełne wyjaśnienie
Adnotacja @Autowired
pozwala pominąć konfigurację gdzie indziej, co wstrzyknąć i po prostu robi to za Ciebie. Zakładając, że Twój Pakiet to com.mycompany.movies
, musisz umieścić ten znacznik w swoim XML (kontekst aplikacji plik):
<context:component-scan base-package="com.mycompany.movies" />
Ten znacznik wykona automatyczne skanowanie. Zakładając, że każda klasa, która ma zostać fasolą, jest opatrzona poprawną adnotacją, taką jak @Component
(dla simple bean) lub @Controller
(dla kontrolki servlet) lub @Repository
(dla klas DAO
) i te klasy znajdują się gdzieś pod pakietem com.mycompany.movies
, Spring znajdzie je wszystkie i utworzy fasolę dla każdej z nich. Odbywa się to w 2 skanach klas - po raz pierwszy wyszukuje klasy, które muszą stać się fasolą i mapuje zastrzyki trzeba zrobić, a na drugim skanowaniu wstrzykuje fasolę. Oczywiście możesz zdefiniować swoje fasolki w bardziej tradycyjnym pliku XML lub za pomocą klasy @Configuration (lub dowolnej kombinacji tych trzech).
Adnotacja @Autowired
informuje sprężynę, gdzie trzeba wykonać zastrzyk. Jeśli umieścisz go na metodzie setMovieFinder
rozumie (przez prefiks set
+ adnotację @Autowired
), że fasola musi zostać wstrzyknięta. W drugim skanie Spring szuka fasoli typu MovieFinder
, a jeśli znajduje taką fasolę, wstrzykuje ją do tej metody. Jeśli znajdzie dwie takie fasolki dostaniesz Exception
. Aby uniknąć Exception
, możesz użyć adnotacji @Qualifier
i powiedzieć, którą z dwóch fasolek wstrzyknąć w następujący sposób:
@Qualifier("redBean")
class Red implements Color {
// Class code here
}
@Qualifier("blueBean")
class Blue implements Color {
// Class code here
}
Lub jeśli wolisz zadeklarować fasolę w swoim XML, wyglądałoby to mniej więcej tak:
<bean id="redBean" class="com.mycompany.movies.Red"/>
<bean id="blueBean" class="com.mycompany.movies.Blue"/>
W deklaracji @Autowired
Należy również dodać @Qualifier
, aby określić, który z dwóch kolorów należy wstrzyknąć:
@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
this.color = color;
}
Jeśli nie chcesz użyj dwóch adnotacji (@Autowired
i @Qualifier
) możesz użyć @Resource
, aby połączyć te dwa:
@Resource(name="redBean")
public void setColor(Color color) {
this.color = color;
}
@Resource
(możesz przeczytać dodatkowe dane na ten temat w pierwszym komentarzu do tej odpowiedzi) oszczędza Ci korzystanie z dwóch adnotacji, a zamiast tego używasz tylko jednej.
Dodam jeszcze dwa komentarze:
- dobrą praktyką byłoby użycie
@Inject
zamiast@Autowired
, ponieważ nie jest to specyficzne dla wiosny i jest częścią standarduJSR-330
. - kolejna dobra praktyka byłoby umieścić
@Inject
/@Autowired
na konstruktorze zamiast metody. Jeśli umieścisz go w konstruktorze, możesz potwierdzić, że wstrzykiwane fasolki nie są null i szybko się nie powiodą podczas próby uruchomienia aplikacji i uniknąćNullPointerException
, gdy musisz faktycznie użyć fasolki.
Update: aby uzupełnić obrazek, stworzyłem nowe pytanie dotyczące klasy @Configuration
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-01 06:46:45
Nic w przykładzie nie mówi, że "klasy implementujące ten sam interfejs". MovieCatalog
jest typem i {[3] } jest innym typem. Wiosna może je łatwo odróżnić.
Jakie przykłady show to różne sposoby, za pomocą których można wstrzykiwać fasolki do pól, metod i konstruktorów.
XML zawiera już wszystkie informacje, których Spring potrzebuje, ponieważ musisz podać w pełni kwalifikowaną nazwę klasy w każdej fasoli. Trzeba jednak uważać na interfejsy:
To autowirowanie się nie powiedzie:
@Autowired
public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }
Ponieważ Java nie przechowuje nazw parametrów w kodzie bajtowym, Spring nie może już odróżnić tych dwóch fasoli. Poprawką jest użycie @Qualifier
:
@Autowired
public void prepare( @Qualifier("bean1") Interface1 bean1,
@Qualifier("bean2") Interface1 bean2 ) { ... }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-28 10:52:51
Tak, możesz skonfigurować plik XML kontekstu serwletów Spring tak, aby definiował Twoje beans (np. klasy), tak aby mógł on wykonać automatyczne Wtrysk za Ciebie. Należy jednak pamiętać, że musisz zrobić inne konfiguracje, aby mieć sprężynę i działa, a najlepszym sposobem, aby to zrobić, jest postępować zgodnie z samouczkiem ziemi.
Po skonfigurowaniu sprężyny prawdopodobnie możesz wykonać następujące czynności w pliku XML kontekstu serwletów Springa, na przykład 1 powyżej (proszę zastąpić pakiet nazwa kom.movies to what the true package name is and if this is a 3rd party class, then be sure that the appropriate jar file is on the classpath):
<beans:bean id="movieFinder" class="com.movies.MovieFinder" />
Lub jeśli Klasa MovieFinder ma konstruktor o prymitywnej wartości, możesz zrobić coś takiego,
<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
<beans:constructor-arg value="100" />
</beans:bean>
Lub jeśli Klasa MovieFinder ma konstruktor oczekujący innej klasy, możesz zrobić coś takiego,
<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
<beans:constructor-arg ref="otherBeanRef" />
</beans:bean>
...gdzie "otherBeanRef " to kolejna fasola, która ma odniesienie do oczekiwanej klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-17 00:29:00
@Autowired
Niech Spring automatycznie przełączy inne fasolki do Twoich klas za pomocą adnotacji @ Autowired.
@Service
public class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyDAO companyDAO;
...
}
Wiosenna końcówka adnotacji fasola Wiosenna może być Przewodowa według nazwy lub typu. @Autowire domyślnie jest wtryskiem typu driven. Adnotacja sprężyny @ Qualifier może być użyta do dalszego dostrojenia autowiringu. @ Resource (javax.adnotacja.Resource) adnotacja może być używana do okablowania według nazwy. Ziarna, które same są zdefiniowane jako zbiór lub typ mapy, nie mogą być wstrzykiwane przez @ Autowired, bo Dopasowanie typu nie ma do nich odpowiedniego zastosowania. Użyj @ Resource dla takich fasoli, odnosząc się do konkretnej kolekcji lub map bean przez unikalną nazwę
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-28 23:31:28