본문 바로가기

Web/spring

[Spring Framework core] 1.10. Classpath Scanning and Managed Components (1)

728x90

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-classpath-scanning

 

Core Technologies

In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do

docs.spring.io

 

틀린 해석이 있다면 알려주세요 🍃

 


1.10. Classpath Scanning and Managed Components~1.10.4. Using Filters to Customize Scanning

 

 

1.10. Classpath Scanning and Managed Components

 

여기서 나올 대부분의 예제는 XML을 사용하여 Spring container 내에서 각 BeanDefinition을 생성하는 구성 메타데이터를 지정한다.

클래스 경로를 스캔하여 후보 구성 요소를 암시적으로 감지하는 옵션에 대해 설명한다.

후보 구성 요소는 필터 기준과 일치하고 해당 빈 정의가 컨테이너에 등록된 클래스이다.

이렇게 하면 빈 등록을 수행하기 위해 XML을 사용할 필요가 없다.

대신 주석(예: @Component), AspectJ 유형 표현식 또는 자신의 사용자 정의 필터 기준을 사용하여 컨테이너에 등록된 빈 정의가 있는 클래스를 선택할 수 있다.

 

Take a look at the @Configuration, @Bean, @Import, and @DependsOn annotations for examples of how to use these features.

 

 

1.10.1. @Component and Further Stereotype Annotations

@Repository 주석은 저장소(Data Access Object 또는 DAO라고도 함)의 역할 또는 스테레오타입을 수행하는 모든 클래스에 대한 Marker 이다. 이 마커의 용도 중에는 예외 변환에 설명된 대로 예외의 자동 변환이 있다.

  

Spring은 @Component, @Service 및 @Controller와 같은 추가 스테레오타입 주석을 제공하고 있다.

@Component는 모든 Spring 관리 구성 요소에 대한 일반적인 스테레오타입이다.

@Repository, @Service 및 @Controller는 보다 구체적인 사용 사례(각각 지속성, 서비스 및 프레젠테이션 계층에서)를 위한 @Component의 특수화이다.

 

따라서 @Component로 구성 요소 클래스에 주석을 달 수 있지만 대신 @Repository, @Service 또는 @Controller로 주석을 달면 클래스가 도구로 처리하거나 측면과 연결하는 데 더 적합하다.

 

예를 들어, 이러한 스테레오타입 주석은 point-cut의 이상적인 대상이 된다.

@Repository, @Service 및 @Controller는 Spring Framework의 향후 릴리스에서 추가 시맨틱을 수행할 수 있다.

따라서 서비스 계층에 대해 @Component 또는 @Service 중에서 선택하는 경우 @Service가 분명히 더 나은 선택이다.

마찬가지로 앞에서 언급했듯이 @Repository는 지속성 계층에서 automatic exception translation을 위한 마커로 이미 지원된다.

https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#orm-exception-translation

 

Data Access

The Data Access Object (DAO) support in Spring is aimed at making it easy to work with data access technologies (such as JDBC, Hibernate, or JPA) in a consistent way. This lets you switch between the aforementioned persistence technologies fairly easily, a

docs.spring.io

 

 

 

 

 

1.10.2. Using Meta-annotations and Composed Annotations

실제 @Service code

Spring에서 제공하는 많은 주석은 자신의 코드에서 메타 주석으로 사용할 수 있다.

메타 주석은 다른 주석에 적용할 수 있는 주석이며, 예를 들어 앞에서 언급한 @Service 주석은 @Component로 메타 주석이 추가된다

 

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // <<여기!
public @interface Service {

    // ...
}

 

메타 주석을 결합하여 "composed annotations"를 만들 수 있다.

Spring MVC의 @RestController 주석은 @Controller와 @ResponseBody로 구성되어있다.

composed annotations은 선택적으로 메타 주석의 속성을 다시 선언하여 사용자 정의를 허용할 수 있다.

이는 메타 주석 속성의 하위 집합만 노출하려는 경우에 특히 유용하게 사용할 수 있다.

 

예를 들어 Spring의 @SessionScope 주석은 범위 이름을 세션에 하드 코딩하지만 여전히 proxyMode의 사용자 정의를 허용한다.

 

다음 목록은 SessionScope 애노테이션의 definition이다

 

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {

    /**
     * Alias for {@link Scope#proxyMode}.
     * <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.
     */
    @AliasFor(annotation = Scope.class)
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}
 

 

 

proxyMode 없이 @SessionScope를 사용할 수 있습니다.

@Service
@SessionScope
public class SessionScopedService {
    // ...
}

 

proxyMode 에 값을 override 할 수 있다

 
 
@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {
    // ...
}

 

 

https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model

 

Spring Annotation Programming Model

Spring Framework. Contribute to spring-projects/spring-framework development by creating an account on GitHub.

github.com

 

 

 

 

1.10.3. Automatically Detecting Classes and Registering Bean Definitions

Spring 은 이 StereoType class를 자동으로 감지하여 해당 BeanDefinition 인스턴스를 ApplicationContext에 등록할 수 있다.

 

@Service
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}
@Repository
public class JpaMovieFinder implements MovieFinder {
    // implementation elided for clarity
}

이런 식으로 쓰면 됨

 

 

만약 클래스를 자동 감지해 해당 bean을 등록시키려면, @Configuration class에 @ComponentScan을 추가하면 된다

basePackages 속성은 두 클래스의 공통 상위 패키지이다

상위 패키지를 포함하는 쉼표, 세미콜론, 공백으로 목록 지정이 가능하다

 

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    // ...
}

 

For brevity, the preceding example could have used the value attribute of the annotation 

(that is, @ComponentScan("org.example")). << 이렇게 써도 됨

 

 

XML사용시

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

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

</beans>

 

 <context:component-scan>을 사용하면 <context:annotation-config>의 기능이 암시적으로 활성화된다.

일반적으로 <context:component-scan>을 사용할 때 <context:annotation-config> 요소를 포함할 필요가 없다

 

 

 

 

**

클래스 경로 패키지를 스캔하려면 클래스 경로에 해당 디렉토리 항목이 있어야 한다.

Ant로 JAR을 빌드할 때 JAR 태스크의 파일 전용 스위치를 활성화하지 않도록 해야한다.

또한 클래스 경로 디렉토리는 일부 환경의 보안 정책에 따라 노출되지 않을 수 있다.

(https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).  

 

JDK 9의 모듈 경로(Jigsaw)에서 Spring의 클래스 경로 스캔은 일반적으로 예상대로 작동한다.

그러나 컴포넌트 클래스가 module-info 디스크립터로 내보내졌는지 확인해야한다.

Spring이 클래스의 비공개 멤버를 호출할 것으로 예상되는 경우 'opened'인지 (즉, 모듈 정보 설명자에서 내보내기 선언 대신 opens 선언을 사용하는지) 확인해야한다.

 

 

또한 component-scan 요소를 사용할 때 AutowiredAnnotationBeanPostProcessor및 CommonAnnotationBeanPostProcessor가 모두 암시적으로 포함된다. 

즉, XML로 제공되는 빈 구성 메타데이터 없이 두 구성 요소가 자동으로 감지되고 함께 연결된다.

 

 

false 값이 있는 annotation-config 특성을 포함하여 

AutowiredAnnotationBeanPostProcessor 및 CommonAnnotationBeanPostProcessor의 등록을 비활성화할 수 있다

 

 

 

 

1.10.4. Using Filters to Customize Scanning

기본적으로 @Component, @Repository, @Service, @Controller, @Configuration 애노테이션이 달린 클래스이거나나 자체에 @Component로 주석이 달린 custom annotation은 유일한 detected candidate components이다.

그리고, custom filters를 적용하여 이 동작을 수정하고 확장할 수 있다.

@ComponentScan 주석의 includeFilters 또는 excludeFilters 속성으로(또는 XML 구성에서 <context:component-scan> 요소의 <context:include-filter /> 또는 <context:exclude-filter /> 하위 요소로) 추가하면 된다.

각 필터 요소에는 유형 및 표현식 속성이 필요하다. 

 

 

Filter Type

Filter Type ExpressionDescription Description
annotation (default) org.example.SomeAnnotation An annotation to be present or meta-present at the type level in target components.
assignable org.example.SomeClass A class (or interface) that the target components are assignable to (extend or implement).
aspectj org.example..*Service+ An AspectJ type expression to be matched by the target components.
regex org\.example\.Default.* A regex expression to be matched by the target components' class names.
custom org.example.MyTypeFilter A custom implementation of the org.springframework.core.type.TypeFilter interface.
 

 

모든 @Respository 애노테이션을 무시하고 대신 "stub" 레포지토리만 사용하는 구성 예시

@Configuration
@ComponentScan(basePackages = "org.example",
        includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
        excludeFilters = @Filter(Repository.class))
public class AppConfig {
    // ...
}

XML로 짜면

<beans>
    <context:component-scan base-package="org.example">
        <context:include-filter type="regex"
                expression=".*Stub.*Repository"/>
        <context:exclude-filter type="annotation"
                expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
</beans>

 

 

애노테이션에 useDefaultFilters=false를 설정하거나 <component-scan/> 요소의 속성으로 use-default-filters="false"를 제공하여 기본 필터를 비활성화할 수도 있다.

이는 @Component, @Repository, @Service, @Controller, @RestController 또는 @Configuration으로 주석이 추가되거나 메타 주석이 추가된 클래스의 자동 감지를 효과적으로 비활성화한다.

728x90