Development Tip

차이점

yourdevel 2020. 9. 30. 11:36
반응형

차이점 vs


나는 봄 3을 배우고 난 기능성 뒤에를 파악하지 못하는 것 같습니다 <context:annotation-config><context:component-scan>.

내가 읽은 내용에서 그들은 다른 주석 (@Required, @Autowired 등 대 @Component, @Repository, @Service 등)을 처리하는 것처럼 보이지만 읽은 내용에서도 동일한 빈 포스트 프로세서 클래스를 등록합니다.

더 혼동을주기 위해에 annotation-config속성이 있습니다 <context:component-scan>.

누군가이 태그에 대해 밝힐 수 있습니까? 비슷한 점, 다른 점, 하나가 다른 것으로 대체되고 서로를 완성합니다. 둘 중 하나가 필요합니까?


<context:annotation-config> 애플리케이션 컨텍스트에 이미 등록 된 Bean의 어노테이션을 활성화하는 데 사용됩니다 (XML 또는 패키지 스캔으로 정의되었는지 여부에 관계없이).

<context:component-scan>또한 무엇을 할 수있을 <context:annotation-config>뿐만 <context:component-scan>아니라 패키지를 스캔하여 애플리케이션 컨텍스트 내에서 빈을 찾고 등록합니다.

차이점 / 유사점을 보여주기 위해 몇 가지 예를 사용하겠습니다.

A, BC, BC에 주입되는 세 가지 빈의 기본 설정부터 시작하겠습니다 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같이 cccbean 속성을 자동 연결합니다 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 />

컨텍스트를로드하면 결과는 ... 아무것도 없습니다. 빈이 생성되지 않고 빈이 자동 연결되지 않습니다. 아무것도!

첫 번째 단락에서 말했듯 <context:annotation-config />이 애플리케이션 컨텍스트 내에 등록 된 빈에서만 작동 하기 때문 입니다. 세 개의 빈에 대한 XML 구성을 제거했기 때문에 빈이 생성 <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>경우에도 AXML에 수동으로 등록 된 경우 에도 애플리케이션 컨텍스트에 등록 된 모든 Bean에 대해 처리 도구가 여전히 적용됩니다 .

하지만 다음과 같은 XML이 있다면, <context:annotation-config />그리고 둘 다 지정했기 때문에 중복 된 빈을 얻게 <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

보시다시피 <context:component-scan/>논리적으로 CLASSPATH 구성 요소 스캔 및 Java @Configuration 기능 으로 확장 <context:annotation-config/> 됩니다.


Spring에서는 다음 두 가지 작업을 수행 할 수 있습니다.

  1. 콩 자동 배선
  2. 콩의 자동 발견

1. Autowiring
일반적으로 applicationContext.xml 에서 bean을 정의하고 다른 bean은 생성자 또는 setter 메소드를 사용하여 연결됩니다. XML 또는 주석을 사용하여 Bean을 연결할 수 있습니다. 어노테이션을 사용하는 경우 어노테이션을 활성화 <context:annotation-config />하고 applicationContext.xml 에 추가해야 합니다 . 이는 bean (생성자 또는 setter)을 수동으로 연결할 필요가 없기 때문에 applicationContext.xml 의 태그 구조를 단순화합니다 . @Autowire주석 을 사용할 수 있으며 Bean은 유형별로 연결됩니다.

수동 XML 구성을 이스케이프하기위한 단계는 다음과 같습니다.

2. Autodiscovery
Autodiscovery는 applicationContext.xml에<bean> 태그를 추가 할 필요조차 없다는 점에서 XML을 한 단계 더 단순화합니다 . 다음 어노테이션 중 하나로 특정 Bean을 표시하기 만하면 Spring은 표시된 Bean과 해당 종속성을 Spring 컨테이너에 자동으로 연결합니다. 주석은 @Controller , @Service , @Component , @Repository 입니다. 기본 패키지 를 사용 하고 가리키면 Spring은 구성 요소를 자동으로 검색하고 Spring 컨테이너에 연결합니다.<context:component-scan>


결론적으로 :

  • <context:annotation-config />@Autowired 주석 을 사용할 수 있도록 사용 됩니다.
  • <context:component-scan /> is used to determine the search of specific beans and attempt of autowiring.

<context:annotation-config> activates many different annotations in beans, whether they are defined in XML or through component scanning.

<context:component-scan> is for defining beans without using XML

For further information, read:


The difference between the two is really simple!.

<context:annotation-config /> 

Enables you to use annotations that are restricted to wiring up properties and constructors only of beans!.

Where as

<context:component-scan base-package="org.package"/> 

Enables everything that <context:annotation-config /> can do, with addition of using stereotypes eg.. @Component, @Service , @Repository. So you can wire entire beans and not just restricted to constructors or properties!.


<context:annotation-config>: Scanning and activating annotations for already registered beans in spring config xml.

<context:component-scan>: Bean registration + <context:annotation-config>


@Autowired and @Required are targets property level so bean should register in spring IOC before use these annotations. To enable these annotations either have to register respective beans or include <context:annotation-config />. i.e. <context:annotation-config /> works with registered beans only.

@Required enables RequiredAnnotationBeanPostProcessor processing tool
@Autowired enables AutowiredAnnotationBeanPostProcessor processing tool

Note: Annotation itself nothing to do, we need a Processing Tool, which is a class underneath, responsible for the core process.


@Repository, @Service and @Controller are @Component, and they targets class level.

<context:component-scan> it scans the package and find and register the beans, and it includes the work done by <context:annotation-config />.

Migrating XML to Annotations


The <context:annotation-config> tag tells Spring to scan the codebase for automatically resolving dependency requirements of the classes containing @Autowired annotation.

Spring 2.5 also adds support for JSR-250 annotations such as @Resource, @PostConstruct, and @PreDestroy.Use of these annotations also requires that certain BeanPostProcessors be registered within the Spring container. As always, these can be registered as individual bean definitions, but they can also be implicitly registered by including <context:annotation-config> tag in spring configuration.

Taken from Spring documentation of Annotation Based Configuration


Spring provides the capability of automatically detecting 'stereotyped' classes and registering corresponding BeanDefinitions with the ApplicationContext.

According to javadoc of org.springframework.stereotype:

Stereotypes are Annotations denoting the roles of types or methods in the overall architecture (at a conceptual, rather than implementation, level). Example: @Controller @Service @Repository etc. These are intended for use by tools and aspects (making an ideal target for pointcuts).

To autodetect such 'stereotype' classes, <context:component-scan> tag is required.

The <context:component-scan> tag also tells Spring to scan the code for injectable beans under the package (and all its subpackages) specified.


<context:annotation-config>

Only resolves the @Autowired and @Qualifer annotations, thats all, it about the Dependency Injection, There are other annotations that do the same job, I think how @Inject, but all about to resolve DI through annotations.

Be aware, even when you have declared the <context:annotation-config> element, you must declare your class how a Bean anyway, remember we have three available options

  • XML: <bean>
  • @Annotations: @Component, @Service, @Repository, @Controller
  • JavaConfig: @Configuration, @Bean

Now with

<context:component-scan>

It does two things:

  • It scans all the classes annotated with @Component, @Service, @Repository, @Controller and @Configuration and create a Bean
  • It does the same job how <context:annotation-config> does.

Therefore if you declare <context:component-scan>, is not necessary anymore declare <context:annotation-config> too.

Thats all

A common scenario was for example declare only a bean through XML and resolve the DI through annotations, for example

<bean id="serviceBeanA" class="com.something.CarServiceImpl" />
<bean id="serviceBeanB" class="com.something.PersonServiceImpl" />
<bean id="repositoryBeanA" class="com.something.CarRepository" />
<bean id="repositoryBeanB" class="com.something.PersonRepository" />

We have only declared the beans, nothing about <constructor-arg> and <property>, the DI is configured in their own classes through @Autowired. It means the Services use @Autowired for their Repositories components and the Repositories use @Autowired for the JdbcTemplate, DataSource etc..components


<context:component-scan /> implicitly enables <context:annotation-config/>

try with <context:component-scan base-package="..." annotation-config="false"/> , in your configuration @Service, @Repository, @Component works fine, but @Autowired,@Resource and @Inject doesn't work.

This means AutowiredAnnotationBeanPostProcessor will not be enabled and Spring container will not process the Autowiring annotations.


<context:annotation-config/> <!-- is used to activate the annotation for beans -->
<context:component-scan base-package="x.y.MyClass" /> <!-- is for the Spring IOC container to look for the beans in the base package. -->

The other important point to note is that context:component-scan implicitly calls the context:annotation-config to activate the annotations on beans. Well if you don't want context:component-scan to implicitly activate annotations for you, you can go on setting the annotation-config element of the context:component-scan to false.

To summarize:

<context:annotation-config/> <!-- activates the annotations --> 
<context:component-scan base-package="x.y.MyClass" /> <!-- activates the annotations + register the beans by looking inside the base-package -->

A <context:component-scan/> custom tag registers the same set of bean definitions as is done by , apart from its primary responsibility of scanning the java packages and registering bean definitions from the classpath.

If for some reason this registration of default bean definitions are to be avoided, the way to do that is to specify an additional "annotation-config" attribute in component-scan, this way:

<context:component-scan basePackages="" annotation-config="false"/>

Reference: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html


<context:component-scan base-package="package name" />:

This is used to tell the container that there are bean classes in my package scan those bean classes. In order to scan bean classes by container on top of the bean we have to write one of the stereo type annotation like following.

@Component, @Service, @Repository, @Controller

<context:annotation-config />:

If we don't want to write bean tag explicitly in XML then how the container knows if there is a auto wiring in the bean. This is possible by using @Autowired annotation. we have to inform to the container that there is auto wiring in my bean by context:annotation-config.


<context:annotation-config>:

This tells Spring that I am going to use Annotated beans as spring bean and those would be wired through @Autowired annotation, instead of declaring in spring config xml file.

<context:component-scan base-package="com.test..."> :

This tells Spring container, where to start searching those annotated beans. Here spring will search all sub packages of the base package.


you can find more information in spring context schema file. following is in spring-context-4.3.xsd

<conxtext:annotation-config />
Activates various annotations to be detected in bean classes: Spring's @Required and
@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),
JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's
@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may
choose to activate the individual BeanPostProcessors for those annotations.

Note: This tag does not activate processing of Spring's @Transactional or EJB 3's
@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>
tag for that purpose.
<context:component-scan>
Scans the classpath for annotated components that will be auto-registered as
Spring beans. By default, the Spring-provided @Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, and @Configuration stereotypes    will be detected.

Note: This tag implies the effects of the 'annotation-config' tag, activating @Required,
@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit
annotations in the component classes, which is usually desired for autodetected components
(without external configuration). Turn off the 'annotation-config' attribute to deactivate
this default behavior, for example in order to use custom BeanPostProcessor definitions
for handling those annotations.

Note: You may use placeholders in package paths, but only resolved against system
properties (analogous to resource paths). A component scan results in new bean definitions
being registered; Spring's PropertySourcesPlaceholderConfigurer will apply to those bean
definitions just like to regular bean definitions, but it won't apply to the component
scan settings themselves.

As a complementary, you can use @ComponentScan to use <context:component-scan> in annotation way.

It's also described at spring.io

Configures component scanning directives for use with @Configuration classes. Provides support parallel with Spring XML's element.

One thing to note, if you're using Spring Boot, the @Configuration and @ComponentScan can be implied by using @SpringBootApplication annotation.

참고URL : https://stackoverflow.com/questions/7414794/difference-between-contextannotation-config-vs-contextcomponent-scan

반응형