Spring Aware interface
Table of Contents
1 Code
package org.springframework.beans.factory; /** * A marker superinterface indicating that a bean is eligible to be notified by the * Spring container of a particular framework object through a callback-style method. * The actual method signature is determined by individual subinterfaces but should * typically consist of just one void-returning method that accepts a single argument. * ... */ public interface Aware { }
Spring 컨테이너가 콜백 스타일로 bean에 대한 알림을 받을 수 있다. 하지만 실제 구현은 이것을 확장해서 알아서 구현하는 것인다. 이것이 왜 필요하냐면 구현 방법은 천차만별이지만 알림을 받고 싶다면 이 인터페이스를 구현해야 한다는 것처럼 보인다.
실제로 Aware
마커 인터페이스가 실제로 사용되는 곳은 어디가 있을까?
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { }
이 클래스는 저자에 로드존슨이 있는 것으로 보아서 아주 오래된 코드이다. ( @since 13.02.2004
)
기본 빈 생성을 구현하는 추상 빈 팩토리 슈퍼클래스로, RootBeanDefinition 클래스에 지정된 모든 기능을 갖추고 있습니다. AbstractBeanFactory의 createBean 메서드에 추가하여 AutowireCapableBeanFactory 인터페이스를 구현합니다.
빈 생성(생성자 해결 포함), 속성 채우기, 배선(자동 배선 포함) 및 초기화를 제공합니다. 런타임 빈 참조를 처리하고, 관리되는 컬렉션을 확인하고, 초기화 메서드를 호출하는 등의 작업을 수행합니다. 자동 배선 생성자, 이름별 속성 및 유형별 속성을 지원합니다.
서브클래스가 구현하는 주요 템플릿 메서드는 유형별 자동 와이어링에 사용되는 resolveDependency(DependencyDescriptor, String, Set, TypeConverter)입니다. 빈 정의를 검색할 수 있는 팩토리의 경우, 일반적으로 이러한 검색을 통해 일치하는 빈을 구현합니다. 다른 팩토리 스타일의 경우, 단순화된 매칭 알고리즘을 구현할 수 있습니다.
이 클래스는 빈 정의 레지스트리 기능을 가정하거나 구현하지 않는다는 점에 유의하세요. 이러한 팩토리의 API 및 SPI 보기를 각각 나타내는 org.springframework.beans.factory.ListableBeanFactory 및 BeanDefinitionRegistry 인터페이스의 구현에 대해서는 DefaultListableBeanFactory를 참조하십시오.
1.1 RootBeanDefinition
루트 빈 정의는 런타임에 Spring BeanFactory의 특정 빈을 뒷받침하는 병합된 빈 정의를 나타냅니다. 루트 빈 정의는 서로 상속하는 여러 개의 원본 빈 정의에서 생성될 수 있으며, 일반적으로 GenericBeanDefinitions로 등록됩니다. 루트 빈 정의는 본질적으로 런타임에 '통합된' 빈 정의 보기입니다.
루트 빈 정의는 구성 단계에서 개별 빈 정의를 등록하는 데에도 사용될 수 있습니다. 그러나 Spring 2.5부터 프로그래밍 방식으로 빈 정의를 등록하는 데 선호되는 방법은 GenericBeanDefinition 클래스입니다. GenericBeanDefinition은 루트 빈 정의로서의 역할을 '하드 코딩'하지 않고 상위 종속성을 동적으로 정의할 수 있다는 이점이 있습니다.
1.2 ChildBeanDefinition
부모로부터 설정을 상속하는 빈에 대한 빈 정의입니다. 자식 빈 정의는 부모 빈 정의에 대한 고정 종속성을 갖습니다.
자식 빈 정의는 부모로부터 생성자 인수 값, 속성 값 및 메서드 재정의와 함께 새 값을 추가할 수 있는 옵션을 상속받습니다. 초기화 메서드, 파괴 메서드 및/또는 정적 팩토리 메서드가 지정된 경우 해당 부모 설정이 재정의됩니다.
나머지 설정은 항상 자식 정의에서 가져옵니다: 의존성, 자동 와이어 모드, 의존성 검사, 싱글톤, 지연 초기화.
참고: Spring 2.5부터 프로그래밍 방식으로 빈 정의를 등록하는 데 선호되는 방법은 GenericBeanDefinition 클래스이며, 이 클래스는 GenericBeanDefinition.setParentName 메서드를 통해 상위 종속성을 동적으로 정의할 수 있습니다. 이 클래스는 대부분의 사용 사례에서 ChildBeanDefinition 클래스를 효과적으로 대체합니다.
1.3 GenericBeanDefinition
GenericBeanDefinition은 표준 빈 정의를 위한 원스톱 상점. 표준적인 BeanDefinition 을 만들 때 씀. 다른 빈 정의와 마찬가지로 클래스와 선택적으로 생성자 인수 값 및 속성 값을 지정할 수 있습니다. 또한 부모 빈 정의에서 파생된 빈은 "parentName" 속성을 통해 유연하게 구성할 수 있습니다.
일반적으로 사용자가 볼 수 있는 빈 정의(포스트 프로세서가 작동하여 부모 이름을 재구성할 수도 있는)를 등록할 목적으로 이 GenericBeanDefinition 클래스를 사용합니다. 부모/자식 관계가 미리 결정되어 있는 경우 RootBeanDefinition / ChildBeanDefinition을 사용합니다.
그럼 일반적으로 어디서 어떻게 쓰일까?
1.3.1 EntityScanner
Spring Boot 애플리케이션이 클래스 패스를 스캔하여 특정 어노테이션이 붙은 클래스를 찾는 데 사용됩니다. 이 클래스는 주로 JPA 엔티티나 Spring Data 레포지토리와 같이 특정 어노테이션이 붙은 클래스를 찾는 데 사용됩니다.
아래가 주요 메소드 이다.
public class EntityScanner { private final ApplicationContext context; public EntityScanner(ApplicationContext context) { Assert.notNull(context, "Context must not be null"); this.context = context; } public final Set<Class<?>> scan(Class<? extends Annotation>... annotationTypes) throws ClassNotFoundException { List<String> packages = getPackages(); if (packages.isEmpty()) { return Collections.emptySet(); } ClassPathScanningCandidateComponentProvider scanner = createClassPathScanningCandidateComponentProvider( this.context); for (Class<? extends Annotation> annotationType : annotationTypes) { scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType)); } Set<Class<?>> entitySet = new HashSet<>(); for (String basePackage : packages) { if (StringUtils.hasText(basePackage)) { for (BeanDefinition candidate : scanner.findCandidateComponents(basePackage)) { entitySet.add(ClassUtils.forName(candidate.getBeanClassName(), this.context.getClassLoader())); } } } return entitySet; } }
1.4 AbstractBeanDefinition
BeanDefinition 클래스를 만들기 위한 위한 베이스 클래스. GenericBeanDefinition, RootBeanDefinition 및 ChildBeanDefinition에서 사용
BeanDefinition을 인자로 받아서 기본적인 설정을 수행하는 BeanDefinition 추상클래스이다. (꼭 필요하지만 별거 아닌 코드를 전부 대신 해준다)
- Bean 클래스 정보를 조회할 수 있게 해준다.
public void setBeanClassName(@Nullable String beanClassName) { this.beanClassName = beanClassName; } @Nullable public String getBeanClassName() { return this.beanClassName; }
- Scope
public void setScope(@Nullable String scope) { this.scope = scope; } @Nullable public String getScope() { return this.scope; }
뭐 이런 것들이다.
1.5 BeanDefinition
BeanDefinition은 해당 Bean의 여러가지 정보들을 가지고 있다. (property values, constructor argument values, and further information supplied by concrete implementations.)
스프링 컨테이너는 이 BeanDefinition을 기반으로 Bean이 생성된다. xml이건, java 코드건 모두 BeanDefinition만 만들면 Bean을 생성할 수 있다.
주요 메서드들을 보면 다음과 같다.
getBeanClassName() getDependsOn() getInitMethodName() getScope() isLazyInit() isPrimary() isSingleton() ...
1.5.1 BeanMetadataElement
package org.springframework.beans; public interface BeanMetadataElement { /** * Return the configuration source {@code Object} for this metadata element * (may be {@code null}). */ @Nullable default Object getSource() { return null; } }
주석처럼 메타데이터 요소를 위한 configuration source를 리턴함.
1.5.2 AttributeAccessor
package org.springframework.core; public interface AttributeAccessor { void setAttribute(String name, @Nullable Object value); @Nullable Object getAttribute(String name); @SuppressWarnings("unchecked") default <T> T computeAttribute(String name, Function<String, T> computeFunction) { Assert.notNull(name, "Name must not be null"); Assert.notNull(computeFunction, "Compute function must not be null"); Object value = getAttribute(name); if (value == null) { value = computeFunction.apply(name); Assert.state(value != null, () -> String.format("Compute function must not return null for attribute named '%s'", name)); setAttribute(name, value); } return (T) value; } @Nullable Object removeAttribute(String name); boolean hasAttribute(String name); String[] attributeNames(); }
임의의 객체에 메타데이터를 담아서 액세스하기 위한 메소드들을 정의함.