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 추상클래스이다. (꼭 필요하지만 별거 아닌 코드를 전부 대신 해준다)

  1. Bean 클래스 정보를 조회할 수 있게 해준다.
public void setBeanClassName(@Nullable String beanClassName) {
	this.beanClassName = beanClassName;
}

@Nullable
public String getBeanClassName() {
	return this.beanClassName;
}
  1. 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();

}

임의의 객체에 메타데이터를 담아서 액세스하기 위한 메소드들을 정의함.

Date: 2023-05-15 Mon 00:00

Author: Younghwan Nam

Created: 2024-05-02 Thu 03:16

Emacs 27.2 (Org mode 9.4.4)

Validate