나는 봄 3을 배우고 난 기능성 뒤에를 파악하지 못하는 것 같습니다 <context:annotation-config>
및 <context:component-scan>
.
내가 읽은 것에서 그들은 다른 주석 ( @Required
, @Autowired
etc vs , 등) 을 처리하는 것처럼 보이지만 @Component
, 읽은 것에서도 동일한 bean post processor 클래스를 등록합니다 .@Repository
@Service
나를 더 혼란스럽게하기 위해에 annotation-config
속성이 있습니다 <context:component-scan>
.
누군가이 태그를 밝힐 수 있습니까? 무엇이 비슷한가, 무엇이 다른가, 하나는 다른 것으로 대체되고, 그들은 서로를 완성하며, 나는 그들 중 하나가 필요합니까?
답변
<context:annotation-config>
응용 프로그램 컨텍스트에 이미 등록 된 Bean에서 주석을 활성화하는 데 사용됩니다 (XML 또는 패키지 스캔으로 정의 된 경우에 상관없이).
<context:component-scan>
또한 무엇을 할 수 <context:annotation-config>
않고 <context:component-scan>
애플리케이션 컨텍스트 내에서 콩을 찾아 등록 패키지를 스캔도.
차이점 / 유사성을 보여주기 위해 몇 가지 예를 사용하겠습니다.
세 종류의 콩의 기본 설정으로 시작하자 A
, B
과 C
함께 B
그리고 C
주입되는 A
.
package com.xxx;
public class B {
public B() {
System.out.println("creating bean B: " + this);
}
}
package com.xxx;
public class C {
public C() {
System.out.println("creating bean C: " + this);
}
}
package com.yyy;
import com.xxx.B;
import com.xxx.C;
public class A {
private B bbb;
private C ccc;
public A() {
System.out.println("creating bean A: " + this);
}
public void setBbb(B bbb) {
System.out.println("setting A.bbb with " + bbb);
this.bbb = bbb;
}
public void setCcc(C ccc) {
System.out.println("setting A.ccc with " + ccc);
this.ccc = ccc;
}
}
다음과 같은 XML 구성을 사용하십시오.
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A">
<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />
</bean>
컨텍스트를로드하면 다음과 같은 출력이 생성됩니다.
creating bean B: com.xxx.B@c2ff5
creating bean C: com.xxx.C@1e8a1f6
creating bean A: com.yyy.A@1e152c5
setting A.bbb with com.xxx.B@c2ff5
setting A.ccc with com.xxx.C@1e8a1f6
이것은 예상 된 결과입니다. 그러나 이것은 “오래된 스타일”봄입니다. 이제 주석이 있으므로 주석을 사용하여 XML을 단순화 할 수 있습니다.
먼저 다음 bbb
과 같이 ccc
bean 에서 and 속성을 자동 와이어 링합니다 A
.
package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.B;
import com.xxx.C;
public class A {
private B bbb;
private C ccc;
public A() {
System.out.println("creating bean A: " + this);
}
@Autowired
public void setBbb(B bbb) {
System.out.println("setting A.bbb with " + bbb);
this.bbb = bbb;
}
@Autowired
public void setCcc(C ccc) {
System.out.println("setting A.ccc with " + ccc);
this.ccc = ccc;
}
}
이를 통해 XML에서 다음 행을 제거 할 수 있습니다.
<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />
내 XML은 이제 다음과 같이 단순화되었습니다.
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
컨텍스트를로드하면 다음과 같은 결과가 나타납니다.
creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf
좋아, 이건 잘못이야! 어떻게 된 거예요? 왜 내 속성이 자동으로 연결되지 않습니까?
주석은 좋은 기능이지만 그 자체로는 아무것도하지 않습니다. 그들은 단지 주석을 달았습니다. 주석을 찾아서 처리하려면 처리 도구가 필요합니다.
<context:annotation-config>
구조에. 이는 자체 정의 된 동일한 애플리케이션 컨텍스트에 정의 된 Bean에서 찾은 주석에 대한 조치를 활성화합니다.
XML을 다음과 같이 변경하면
<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
응용 프로그램 컨텍스트를로드하면 올바른 결과가 나타납니다.
creating bean B: com.xxx.B@15663a2
creating bean C: com.xxx.C@cd5f8b
creating bean A: com.yyy.A@157aa53
setting A.bbb with com.xxx.B@15663a2
setting A.ccc with com.xxx.C@cd5f8b
좋아, 이것은 훌륭하지만 XML에서 두 개의 행을 제거하고 하나를 추가했습니다. 큰 차이는 아닙니다. 주석이있는 아이디어는 XML을 제거해야한다는 것입니다.
XML 정의를 제거하고 주석으로 모두 바꾸자.
package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class B {
public B() {
System.out.println("creating bean B: " + this);
}
}
package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class C {
public C() {
System.out.println("creating bean C: " + this);
}
}
package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.B;
import com.xxx.C;
@Component
public class A {
private B bbb;
private C ccc;
public A() {
System.out.println("creating bean A: " + this);
}
@Autowired
public void setBbb(B bbb) {
System.out.println("setting A.bbb with " + bbb);
this.bbb = bbb;
}
@Autowired
public void setCcc(C ccc) {
System.out.println("setting A.ccc with " + ccc);
this.ccc = ccc;
}
}
XML에서 우리는 이것을 유지합니다.
<context:annotation-config />
컨텍스트를로드하면 결과는 … Nothing입니다. Bean이 작성되지 않고 Bean이 자동 연결되지 않습니다. 아무것도!
첫 번째 단락에서 말했듯 <context:annotation-config />
이 응용 프로그램 컨텍스트에 등록 된 Bean에서만 작동 하기 때문 입니다. 세 개의 Bean에 대한 XML 구성을 제거했기 때문에 작성된 Bean <context:annotation-config />
이없고 작업 할 “대상”이 없습니다.
그러나 <context:component-scan>
“대상”이 작동하도록 패키지를 스캔 할 수 있는 문제는 아닙니다 . XML 구성의 내용을 다음 항목으로 변경하십시오.
<context:component-scan base-package="com.xxx" />
컨텍스트를로드하면 다음과 같은 결과가 나타납니다.
creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff
흠 … 뭔가 빠졌습니다. 왜?
당신이 클래스에 closelly 보면, 클래스는 A
패키지를 가지고 com.yyy
하지만 난에서 지정한 <context:component-scan>
패키지를 사용하는 com.xxx
이 완전히 내 놓친 있도록 A
클래스를 만 포착 B
하고 C
어느에있는 com.xxx
패키지.
이 문제를 해결하기 위해 다른 패키지도 추가합니다.
<context:component-scan base-package="com.xxx,com.yyy" />
이제 예상 결과를 얻습니다.
creating bean B: com.xxx.B@cd5f8b
creating bean C: com.xxx.C@15ac3c9
creating bean A: com.yyy.A@ec4a87
setting A.bbb with com.xxx.B@cd5f8b
setting A.ccc with com.xxx.C@15ac3c9
그리고 그게 다야! 이제 더 이상 XML 정의가 없으며 주석이 있습니다.
최종 예를 들어, 주석 클래스를 유지 A
, B
그리고 C
우리는 컨텍스트를로드 한 후 무엇을 얻을 것이다, 그리고 XML에 다음을 추가?
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
우리는 여전히 올바른 결과를 얻습니다.
creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87
클래스의 Bean을 A
스캔하여 확보하지 않더라도 처리 도구는 여전히 <context:component-scan>
애플리케이션 컨텍스트에 등록 된 모든 Bean에 적용되며 A
, XML에 수동으로 등록 된 경우 에도 마찬가지입니다 .
그러나 만약 우리가 다음과 같은 XML을 가지고 있다면, <context:annotation-config />
그리고 둘 다 지정했기 때문에 중복 된 bean을 얻게 <context:component-scan>
될까요?
<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
아니요, 중복이 없습니다. 다시 예상 결과를 얻습니다.
creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87
두 태그가 동일한 처리 도구를 지정하기 때문입니다 (지정된 <context:annotation-config />
경우 생략 가능 <context:component-scan>
). 그러나 Spring은 한 번만 실행을 처리합니다.
처리 도구를 여러 번 직접 등록하더라도 Spring은 여전히 한 번만 마법을 수행하도록합니다. 이 XML :
<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
여전히 다음과 같은 결과가 생성됩니다.
creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@25d2b2
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87
좋아, 랩은 끝이야.
@Tomasz Nurkiewicz와 @Sean Patrick Floyd의 답변과 함께이 정보가 방법 <context:annotation-config>
과 <context:component-scan>
작업 을 이해하는 데 필요한 모든 것이기를 바랍니다
.
답변
어떤 주석이 어떤 선언에 의해 선택되었는지에 대한 멋진 요약 을 발견했습니다 . 그것을 연구하면 다음 <context:component-scan/>
과 같이 인식되는 주석의 상위 집합 을 인식합니다 <context:annotation-config/>
.
@Component
,@Service
,@Repository
,@Controller
,@Endpoint
@Configuration
,@Bean
,@Lazy
,@Scope
,@Order
,@Primary
,@Profile
,@DependsOn
,@Import
,@ImportResource
보시다시피 CLASSPATH 구성 요소 검색 및 Java @Configuration 기능 <context:component-scan/>
으로 논리적으로 확장 <context:annotation-config/>
됩니다.
답변
Spring을 사용하면 두 가지 작업을 수행 할 수 있습니다.
- 콩의 자동 배선
- 콩의 자동 발견
1. 자동 배선
보통 applicationContext.xml 에서 bean을 정의하고 다른 bean은 생성자 또는 setter 메소드를 사용하여 연결됩니다. XML 또는 주석을 사용하여 Bean을 연결할 수 있습니다. 주석을 사용하는 경우 주석을 활성화해야 <context:annotation-config />
하며 applicationContext.xml 에 추가해야
합니다 . 이는 bean (생성자 또는 setter)을 수동으로 연결할 필요가 없기 때문에 applicationContext.xml 의 태그 구조를 단순화합니다 . @Autowire
주석 을 사용할 수 있으며 콩은 유형별로 연결됩니다.
수동 XML 구성을 피하기위한 단계는 다음과 같습니다.
2. 자동
검색 자동 검색은 applicationContext.xml에<bean>
태그를 너무 추가 할 필요가 없다는 의미에서 XML을 한 단계 더 단순화합니다 . 다음 주석 중 하나를 사용하여 특정 Bean을 표시하면 Spring은 표시된 Bean 및 해당 종속성을 Spring 컨테이너에 자동으로 연결합니다. 주석은 다음과 같습니다 : @Controller , @Service , @Component , @Repository . 기본 패키지 를 사용 하고 가리키면 Spring은 구성 요소를 자동 검색하여 Spring 컨테이너에 연결합니다.<context:component-scan>
결론적으로 :
<context:annotation-config />
@Autowired 주석 을 사용하기 위해 사용
됩니다<context:component-scan />
특정 Bean의 검색 및 자동 배선 시도를 판별하는 데 사용됩니다.
답변
<context:annotation-config>
XML에 정의되어 있는지 또는 구성 요소 검색을 통해 Bean에있는 여러 가지 주석을 활성화합니다.
<context:component-scan>
XML을 사용하지 않고 Bean을 정의하기위한 것
자세한 내용은 다음을 읽으십시오.
답변
둘의 차이점은 정말 간단합니다.
<context:annotation-config />
Bean의 특성과 생성자 만 연결하도록 제한된 주석을 사용할 수 있습니다.
어디로
<context:component-scan base-package="org.package"/>
모든 것을 가능하게 <context:annotation-config />
고정 관념 예를 들어, 사용의 추가와 함께, 할 수 … @Component
, @Service
, @Repository
. 따라서 생성자 또는 속성에만 국한되지 않고 전체 Bean을 연결할 수 있습니다!.
답변
<context:annotation-config>
: spring config xml에 이미 등록 된 Bean에 대한 주석 스캔 및 활성화.
<context:component-scan>
: 콩 등록 +<context:annotation-config>
@Autowired 및 @Required 는 대상 특성 레벨 이므로이 주석을 사용하기 전에 Bean이 스프링 IOC에 등록해야합니다. 이러한 주석을 사용하려면 각 Bean을 등록하거나 포함해야 <context:annotation-config />
합니다. 즉 <context:annotation-config />
, 등록 된 Bean에서만 작동합니다.
@Required는 수 RequiredAnnotationBeanPostProcessor
처리 도구
@Autowired가 가능 AutowiredAnnotationBeanPostProcessor
가공 공구
참고 : 주석 자체는 아무것도 할 일이 없으므로 핵심 프로세스를 담당하는 클래스 인 Processing Tool이 필요합니다 .
@Repository, @Service 및 @Controller는 @Component 이며 클래스 수준 을 대상으로합니다 .
<context:component-scan>
패키지를 스캔하고 Bean을 찾아 등록하며에 의해 수행 된 작업이 포함됩니다 <context:annotation-config />
.
답변
이 <context:annotation-config>
태그는 Spring에게 @Autowired 주석을 포함하는 클래스의 종속성 요구 사항을 자동으로 해결하기 위해 코드베이스를 스캔하도록 지시합니다.
Spring 2.5는 또한 @Resource, @PostConstruct 및 @PreDestroy와 같은 JSR-250 주석에 대한 지원을 추가합니다. 이러한 주석을 사용하려면 특정 BeanPostProcessors를 Spring 컨테이너 내에 등록해야합니다. 항상 그렇듯이 개별 빈 정의로 등록 할 수 있지만 <context:annotation-config>
스프링 구성에 태그를 포함시켜 암시 적으로 등록 할 수도 있습니다 .
Annotation Based Configuration 의 Spring 문서에서 발췌
Spring은 ‘스테레오 타입’클래스를 자동으로 감지하고 해당 BeanDefinition을 ApplicationContext에 등록하는 기능을 제공합니다.
org.springframework.stereotype의 javadoc에 따르면 :
스테레오 타입은 전체 아키텍처에서 유형 또는 메소드의 역할을 나타내는 주석입니다 (구현 레벨이 아닌 개념적 레벨). 예 : @Controller @Service @Repository 등. 도구 및 측면에서 사용하기위한 것입니다 (포인트 컷에 이상적인 대상 만들기).
이러한 ‘스테레오 타입’클래스를 자동 감지하려면 <context:component-scan>
태그가 필요합니다.
이 <context:component-scan>
태그는 또한 지정된 패키지 (및 모든 서브 패키지) 아래에 코드로 주사 가능한 빈을 스캔하도록 Spring에 지시합니다.