Uczę się wiosny 3 i wydaje mi się, że nie rozumiem funkcjonalności stojącej za <context:annotation-config>
i <context:component-scan>
.
Z tego co czytałem wydają się obsługiwać różne adnotacje ( @Required
, @Autowired
etc vs @Component
, @Repository
, @Service
etc), ale również z tego co czytałem rejestrują te same procesory fasola pocztowe klas.
Mylić mnie jeszcze bardziej, jest annotation-config
atrybut na <context:component-scan>
.
Czy ktoś może rzucić nieco światła na te tagi? Co jest podobne, co inne, jedno jest zastępowane przez drugie, uzupełniają się nawzajem, czy potrzebuję jednego z nich, obu?
java
spring
configuration
annotations
spring-3
użytkownik938214097
źródło
źródło
component-scan
gdy tylko jest to możliwe.Odpowiedzi:
<context:annotation-config>
służy do aktywacji adnotacji w komponentach bean już zarejestrowanych w kontekście aplikacji (bez względu na to, czy zostały one zdefiniowane za pomocą XML, czy poprzez skanowanie pakietów).<context:component-scan>
może również robić to, co<context:annotation-config>
robi, ale<context:component-scan>
także skanuje pakiety, aby znaleźć i zarejestrować komponenty bean w kontekście aplikacji.Wykorzystam kilka przykładów, aby pokazać różnice / podobieństwa.
Zacznijmy od podstawowej konfiguracji trzech ziaren tego typu
A
,B
iC
,B
iC
wstrzyknięcia doA
.Dzięki następującej konfiguracji XML:
Ładowanie kontekstu daje następujące wyniki:
OK, to oczekiwany wynik. Ale to wiosna w „starym stylu”. Teraz mamy adnotacje, więc wykorzystajmy je, aby uprościć XML.
Po pierwsze, pozwala na automatyczne
bbb
iccc
właściwości bean w następującyA
sposób:To pozwala mi usunąć następujące wiersze z pliku XML:
Mój XML jest teraz uproszczony do tego:
Podczas ładowania kontekstu otrzymuję następujące dane wyjściowe:
OK, to źle! Co się stało? Dlaczego moje właściwości nie są tworzone automatycznie?
Cóż, adnotacje są fajną funkcją, ale same w sobie nic nie robią. Po prostu dodają adnotacje. Potrzebujesz narzędzia do przetwarzania, aby znaleźć adnotacje i coś z nimi zrobić.
<context:annotation-config>
na pomoc. To aktywuje akcje dla adnotacji, które znajdzie na komponentach bean zdefiniowanych w tym samym kontekście aplikacji, w którym sama jest zdefiniowana.Jeśli zmienię XML na to:
po załadowaniu kontekstu aplikacji uzyskuję odpowiedni wynik:
OK, to miłe, ale usunąłem dwa wiersze z pliku XML i dodałem jeden. To nie jest bardzo duża różnica. Pomysł z adnotacjami polega na tym, że ma on usunąć XML.
Usuńmy więc definicje XML i zastąpmy je adnotacjami:
Podczas gdy w XML zachowujemy tylko to:
Ładujemy kontekst, a wynik jest ... Nic. Żadne ziarna nie są tworzone, żadne ziarna nie są automatycznie przetwarzane. Nic!
Jest tak, ponieważ, jak powiedziałem w pierwszym akapicie,
<context:annotation-config />
jedyne działa na fasolach zarejestrowanych w kontekście aplikacji. Ponieważ usunąłem konfigurację XML dla trzech ziaren, nie ma żadnego komponentu bean i<context:annotation-config />
nie ma „celów” do pracy.Ale to nie będzie problem, w przypadku
<context:component-scan>
którego można przeskanować pakiet w poszukiwaniu „celów”, nad którymi będzie działać. Zmieńmy zawartość konfiguracji XML na następujący wpis:Podczas ładowania kontekstu otrzymuję następujące dane wyjściowe:
Hmmmm ... czegoś brakuje. Dlaczego?
Jeśli przyjrzysz się bliżej klasom, klasa
A
ma pakiet,com.yyy
ale określiłem go w<context:component-scan>
pakiecie do użycia,com.xxx
więc całkowicie pominąłem mojąA
klasę i tylko odebrałemB
iC
którecom.xxx
pakiecie.Aby to naprawić, dodaję również ten inny pakiet:
a teraz otrzymujemy oczekiwany wynik:
I to wszystko! Teraz nie masz już definicji XML, masz adnotacje.
Jako ostatni przykład, zachowując adnotacjami klas
A
,B
aC
i dodanie następujących do XML, co otrzymamy po załadowaniu kontekst?Nadal otrzymujemy poprawny wynik:
Nawet jeśli fasola dla klasy
A
nie zostanie uzyskana przez skanowanie, narzędzia przetwarzania są nadal stosowane do<context:component-scan>
wszystkich ziaren zarejestrowanych w kontekście aplikacji, nawet dlaA
których została ręcznie zarejestrowana w pliku XML.Ale co, jeśli będziemy mieć następujący kod XML, czy otrzymamy zduplikowane komponenty bean, ponieważ wybraliśmy oba
<context:annotation-config />
i<context:component-scan>
?Nie, bez duplikatów, ponownie otrzymujemy oczekiwany wynik:
Jest tak, ponieważ oba tagi rejestrują te same narzędzia przetwarzania (
<context:annotation-config />
można je pominąć, jeśli<context:component-scan>
jest określony), ale Spring zadba o ich uruchomienie tylko raz.Nawet jeśli zarejestrujesz narzędzia do przetwarzania wiele razy, Spring nadal upewni się, że wykonają swoją magię tylko raz; ten XML:
nadal będzie generować następujący wynik:
OK, chodzi o rapowanie.
Mam nadzieję, że te informacje wraz z odpowiedziami @Tomasz Nurkiewicz i @Sean Patrick Floyd są wszystkim, czego potrzebujesz, aby zrozumieć, jak
<context:annotation-config>
i jak<context:component-scan>
pracować.źródło
Znalazłem to miłe podsumowanie, które adnotacje są zbierane przez które deklaracje. Studiując go, zauważysz, że
<context:component-scan/>
rozpoznaje on zestaw adnotacji rozpoznawanych przez<context:annotation-config/>
, a mianowicie:@Component
,@Service
,@Repository
,@Controller
,@Endpoint
@Configuration
,@Bean
,@Lazy
,@Scope
,@Order
,@Primary
,@Profile
,@DependsOn
,@Import
,@ImportResource
Jak widać,
<context:component-scan/>
logicznie rozszerza się<context:annotation-config/>
o funkcje skanowania komponentów CLASSPATH i Java @Configuration.źródło
Wiosna pozwala zrobić dwie rzeczy:
1. Automatyczne okablowanie
Zwykle w applicationContext.xml definiujesz ziarna, a inne ziarna są podłączone za pomocą metod konstruktora lub ustawiacza. Fasole można łączyć za pomocą XML lub adnotacji. W przypadku korzystania z adnotacji należy je aktywować i dodać
<context:annotation-config />
w pliku applicationContext.xml . Uprości to strukturę tagu z applicationContext.xml , ponieważ nie będziesz musiał ręcznie łączyć bean (konstruktora lub setera). Możesz użyć@Autowire
adnotacji, a fasola zostanie połączona według typu.Krokiem do przodu w zakresie unikania ręcznej konfiguracji XML jest
2. Autodiscovery
Autodiscovery upraszcza XML o krok dalej, w tym sensie, że nawet nie potrzebujesz dodawać
<bean>
znacznika do applicationContext.xml . Po prostu oznaczysz konkretne ziarna za pomocą jednej z poniższych adnotacji, a Spring automatycznie połączy zaznaczone ziarna i ich zależności do pojemnika Spring. Adnotacje są następujące: @Controller , @Service , @Component , @Repository . Używając<context:component-scan>
i wskazując pakiet podstawowy, Spring automatycznie wykryje i podłączy komponenty do pojemnika Spring.Jako podsumowanie:
<context:annotation-config />
jest używany, aby móc korzystać z adnotacji @Autowired<context:component-scan />
służy do określania wyszukiwania określonych ziaren i próby automatycznej instalacji.źródło
<context:annotation-config>
aktywuje wiele różnych adnotacji w komponentach bean, niezależnie od tego, czy są one zdefiniowane w XML, czy poprzez skanowanie komponentów.<context:component-scan>
służy do definiowania ziaren bez użycia XMLAby uzyskać więcej informacji, przeczytaj:
źródło
<context:component-scan>
, nie będę w stanie zastąpić definicji komponentu bean za pomocą XML?<context:component-scan>
? Czy coś tracę, jeśli nie używam<context:annotation-config>
?Różnica między nimi jest naprawdę prosta!.
Umożliwia korzystanie z adnotacji, które ograniczają się do okablowania właściwości i konstruktorów tylko ziaren !.
Natomiast
Umożliwia wszystko, co
<context:annotation-config />
może zrobić, korzystając z dodatkiem stereotypy np ..@Component
,@Service
,@Repository
. Możesz więc połączyć całą fasolę i nie ograniczać się tylko do konstruktorów lub właściwości!źródło
<context:annotation-config>
: Skanowanie i aktywowanie adnotacji dla już zarejestrowanych ziaren w wiosennym pliku konfiguracyjnym xml.<context:component-scan>
: Rejestracja fasoli +<context:annotation-config>
@Autowired i @Required są na poziomie właściwości celu, więc fasola powinna zarejestrować się wiosną MKOl przed użyciem tych adnotacji. Aby włączyć te adnotacje, należy zarejestrować odpowiednie komponenty bean lub dołączyć
<context:annotation-config />
. tzn.<context:annotation-config />
działa tylko z zarejestrowaną fasolą.@Required włącza
RequiredAnnotationBeanPostProcessor
narzędzie do przetwarzania@Autowired umożliwia
AutowiredAnnotationBeanPostProcessor
narzędzie do przetwarzaniaUwaga: sama adnotacja nie ma nic do roboty, potrzebujemy Narzędzia Przetwarzania , które jest pod nią klasą odpowiedzialną za proces podstawowy.
@Repository, @Service i @Controller są @Component i są ukierunkowane na poziom klasy .
<context:component-scan>
skanuje paczkę oraz znajduje i rejestruje ziarna, a także obejmuje pracę wykonaną przez<context:annotation-config />
.Migracja XML do adnotacji
źródło
The
<context:annotation-config>
Tag mówi Wiosna skanować kodzie do automatycznego rozwiązywania wymagania zależność klas zawierających @Autowired adnotacji.Spring 2.5 dodaje także obsługę adnotacji JSR-250, takich jak @Resource, @PostConstruct i @ PreDestroy. Korzystanie z tych adnotacji wymaga również, aby niektóre procesory BeanPostProcesory były zarejestrowane w kontenerze Spring. Jak zawsze można je zarejestrować jako indywidualne definicje komponentu bean, ale można je również domyślnie zarejestrować, włączając
<context:annotation-config>
znacznik do konfiguracji sprężynowej.Zaczerpnięte z wiosennej dokumentacji konfiguracji opartej na adnotacjach
Wiosna umożliwia automatyczne wykrywanie „stereotypowych” klas i rejestrowanie odpowiednich definicji BeanDefinition w ApplicationContext.
Według javadoc z org.springframework.stereotype :
Stereotypy to adnotacje oznaczające role typów lub metod w ogólnej architekturze (na poziomie koncepcyjnym, a nie implementacyjnym). Przykład: @Controller @Service @Repository itp. Są one przeznaczone do użycia przez narzędzia i aspekty (tworząc idealny cel dla skrótów punktowych).
Aby automatycznie wykryć takie „stereotypowe” klasy,
<context:component-scan>
wymagany jest tag.<context:component-scan>
Tag mówi również Wiosna zeskanować kod fasoli iniekcji w ramach pakietu (i wszystkie jego podpakietów) określona.źródło
Rozwiązuje tylko
@Autowired
i@Qualifer
adnotacje, to wszystko, chodzi o wstrzykiwanie zależności. Istnieją inne adnotacje, które wykonują tę samą pracę, myślę, jak@Inject
, ale wszystko w celu rozwiązania DI za pomocą adnotacji.Pamiętaj, że nawet po zadeklarowaniu
<context:annotation-config>
elementu musisz zadeklarować swoją klasę jak Fasola, pamiętaj, że mamy trzy dostępne opcje<bean>
Teraz z
Robi dwie rzeczy:
<context:annotation-config>
robi.Dlatego, jeśli zadeklarujesz
<context:component-scan>
, nie jest już więcej konieczne<context:annotation-config>
.To wszystko
Typowym scenariuszem było na przykład zadeklarowanie tylko fasoli za pomocą XML i rozwiązanie DI na przykład poprzez adnotacje
Mamy tylko zadeklarowane fasolę, nic na ten temat
<constructor-arg>
i<property>
DI jest skonfigurowany w swoich klasach przez @Autowired. Oznacza to, że Usługi używają @Autowired dla swoich komponentów Repozytoriów, a Repozytoria używają @Autowired dla komponentów JdbcTemplate, DataSource itp.źródło
spróbuj
<context:component-scan base-package="..." annotation-config="false"/>
w konfiguracji @Service, @Repository, @Component działa dobrze, ale @ Autowired, @ Resource i @Inject nie działa.Oznacza to, że AutowiredAnnotationBeanPostProcessor nie zostanie włączony, a kontener Spring nie przetworzy adnotacji Autowired.
źródło
Inną ważną kwestią, na którą należy zwrócić uwagę, jest to, że
context:component-scan
domyślnie wywołuje funkcjęcontext:annotation-config
aktywacji adnotacji na fasoli. Dobrze, jeśli nie chceszcontext:component-scan
, aby domyślnie włączyć adnotacje dla ciebie, możesz iść na ustawienie elementu adnotacji-Configcontext:component-scan
dofalse
.Podsumowując:
źródło
<context:component-scan base-package="package name" />
:Służy to do poinformowania kontenera, że w moim pakiecie są klasy fasoli, które skanują te klasy fasoli. Aby przeskanować klasy fasoli według kontenera na górze fasoli, musimy napisać jedną z adnotacji typu stereo, jak poniżej.
@Component
,@Service
,@Repository
,@Controller
<context:annotation-config />
:Jeśli nie chcemy jawnie zapisywać tagu bean w XML, to skąd kontener wie, czy w beanie jest automatyczne okablowanie. Jest to możliwe przy użyciu
@Autowired
adnotacji. musimy poinformować kontener, że w mojej fasoli jest automatyczne okablowaniecontext:annotation-config
.źródło
Znacznik
<context:component-scan/>
niestandardowy rejestruje ten sam zestaw definicji komponentu bean, który jest wykonywany, poza jego główną odpowiedzialnością za skanowanie pakietów java i rejestrowanie definicji komponentu bean ze ścieżki klasy.Jeśli z jakiegoś powodu należy unikać tej rejestracji domyślnych definicji komponentu bean, można to zrobić poprzez określenie dodatkowego atrybutu „adnotation-config” w skanie składników:
Odniesienie: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html
źródło
<context:annotation-config>
:Mówi to Springowi, że użyję fasolki z adnotacjami jako fasoli wiosennej, a te zostaną połączone za pomocą
@Autowired
adnotacji, zamiast deklarować w wiosennym pliku konfiguracyjnym xml.<context:component-scan base-package="com.test...">
:To mówi kontenerowi Spring, gdzie rozpocząć wyszukiwanie fasoli z adnotacjami. Tutaj wiosna przeszuka wszystkie paczki podrzędne pakietu podstawowego.
źródło
więcej informacji można znaleźć w wiosennym pliku schematu kontekstowego. poniżej znajduje się w Spring-context-4.3.xsd
źródło
Jako uzupełnienie możesz użyć
@ComponentScan
do użycia<context:component-scan>
w sposób adnotacji.Jest to również opisane w spring.io
Należy zauważyć, że jeśli używasz Spring Boot, @Configuration i @ComponentScan można implikować za pomocą adnotacji @SpringBootApplication.
źródło