Understanding Spring @ Autowired usage

[[3]] czytam spring 3.0.x reference documentation to understand Spring Autowired adnotation:

3.9.2 @Autowired i @ Inject

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?

Author: Pragati Singh, 2013-10-17

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:

  1. dobrą praktyką byłoby użycie @Inject zamiast @Autowired, ponieważ nie jest to specyficzne dla wiosny i jest częścią standarduJSR-330 .
  2. 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.

 469
Author: Avi,
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ć.

Wiosną 2.x, Okablowanie fasoli odbywało się głównie za pomocą identyfikatorów fasoli lub nazw. Jest to nadal wspierane przez Spring 3.x ale często będziesz miał jedną instancję fasoli z określonym typem-większość usług to singletony. Tworzenie nazw dla nich jest żmudne. Spring zaczął więc wspierać "autowire by type".

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 ) { ... }
 16
Author: Aaron Digulla,
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.

 5
Author: Cem Sultan,
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ę

 5
Author: aman,
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