Container Extension Points(한글)

일반적으로 애플리케이션 개발자는 ApplicationContext 구현 클래스를 서브클래스화할 필요가 없습니다. 대신 특수 통합 인터페이스의 구현을 연결하여 Spring IoC 컨테이너를 확장할 수 있습니다. 다음 몇 섹션에서는 이러한 통합 인터페이스에 대해 설명합니다.

BeanPostProcessor을 사용한 Bean 커스터마이징(Customizing Beans by Using a BeanPostProcessor)

BeanPostProcessor 인터페이스는 자체 인스턴스화 로직, 의존성 해결 로직 등을 제공하기 위해(또는 컨테이너의 기본값을 재정의하기 위해) 구현할 수 있는 콜백 메서드를 정의합니다. Spring 컨테이너가 Bean의 인스턴스화, 구성 및 초기화를 마친 후 사용자 정의 로직을 구현하려는 경우 하나 이상의 사용자 정의 BeanPostProcessor 구현을 플러그인할 수 있습니다.

여러 개의 BeanPostProcessor 인스턴스를 구성할 수 있으며, order 속성을 설정하여 이러한 BeanPostProcessor 인스턴스가 실행되는 순서를 제어할 수 있습니다. 이 property는 BeanPostProcessorOrdered 인터페이스를 구현하는 경우에만 설정할 수 있습니다. 자체 BeanPostProcessor 를 작성하는 경우 Ordered 인터페이스도 구현하는 것을 고려해야 합니다. 자세한 내용은 BeanPostProcessorOrdered 인터페이스의 javadoc을 참조하세요. BeanPostProcessor 인스턴스의 프로그래밍 등록에 대한 참고 사항도 참조하세요.

BeanPostProcessor 인스턴스는 Bean(또는 객체) 인스턴스에서 작동합니다. 즉, Spring IoC 컨테이너가 Bean 인스턴스를 인스턴스화한 다음 BeanPostProcessor 인스턴스가 작업을 수행합니다.

BeanPostProcessor 인스턴스는 컨테이너별로 Scope가 지정됩니다. 이는 컨테이너 계층 구조를 사용하는 경우에만 관련이 있습니다. 하나의 컨테이너에 BeanPostProcessor 를 정의하면 해당 컨테이너에 있는 Bean만 사후 처리합니다. 즉, 두 컨테이너가 동일한 계층에 속해 있더라도 한 컨테이너에 정의된 Bean은 다른 컨테이너에 정의된 BeanPostProcessor 에 의해 사후 처리되지 않습니다.

실제 Bean 정의(즉, Bean을 정의하는 블루프린트)를 변경하려면 BeanFactoryPostProcessor 로 구성 메타데이터 사용자 지정에 설명된 대로 BeanFactoryPostProcessor 를 대신 사용해야 합니다.

org.springframework.beans.factory.config.BeanPostProcessor 인터페이스는 정확히 두 개의 콜백 메서드로 구성됩니다. 이러한 클래스가 컨테이너에 post-processor로 등록되면 컨테이너에 의해 생성되는 각 Bean 인스턴스에 대해 post-processor는 컨테이너 초기화 메서드(예: InitializingBean.afterPropertiesSet() 또는 선언된 모든 init 메서드)가 호출되기 전과 모든 Bean 초기화 콜백 후에 모두 컨테이너로부터 콜백을 가져옵니다. post-processor는 콜백을 완전히 무시하는 것을 포함하여 Bean 인스턴스에 대해 모든 작업을 수행할 수 있습니다. Bean 사후 프로세서는 일반적으로 콜백 인터페이스를 확인하거나 프록시로 Bean을 래핑할 수 있습니다. 일부 Spring AOP 인프라 클래스는 프록시 래핑 로직을 제공하기 위해 Bean post-processor로 구현됩니다.

ApplicationContext 는 자동으로 BeanPostProcessor 인터페이스를 구현하는 구성 메타데이터에 정의된 모든 빈을 자동으로 감지합니다. 그리고 ApplicationContext` 는 이러한 Bean을 post-processor(post-processors)로 등록하여 나중에 Bean이 생성될 때 호출할 수 있도록 post-processor로 등록합니다. Bean post-processor는 컨테이너에 다른 Bean과 동일한 방식으로 컨테이너에 배포할 수 있습니다.

구성 클래스에서 @Bean 팩토리 메서드를 사용하여 BeanPostProcessor 를 선언할 때 주의하십시오. 구성 클래스에서 팩토리 메서드의 반환 유형은 구현된 클래스 자체 또는 최소한 org.springframework.beans.factory.config.BeanPostProcessor 인터페이스여야 합니다. 인터페이스여야 하며, 이는 해당 Bean의 포스트프로세서 특성을 명확하게 나타냅니다. 그렇지 않으면 ApplicationContext 가 완전히 생성되기 전에 유형별로 자동 감지할 수 없습니다. BeanPostProcessor 는 다른 Bean의 초기화에 적용하기 위해 조기에 인스턴스화되어야 하므로 초기화해야 하므로 이 초기 유형 감지는 매우 중요합니다.

프로그래밍 방식으로 BeanPostProcessor 인스턴스 등록하기
BeanPostProcessor 등록을 위해 권장되는 방법은 앞서 설명한 대로 ApplicationContext 자동 감지를 이용하는 것이지만, addBeanPostProcessor 메서드를 사용하여 ConfigurableBeanFactory 에 대해 프로그래밍 방식으로 등록할 수도 있습니다. 이는 등록 전에 조건부 로직을 평가해야 하거나 계층 구조의 컨텍스트 간에 Bean post-processor를 복사해야 할 때 유용할 수 있습니다. 그러나 프로그래밍 방식으로 추가된 BeanPostProcessor 인스턴스는 Ordered 인터페이스를 따르지 않는다는 점에 유의하세요. 여기서 실행 순서를 결정하는 것은 등록 순서입니다. 또한 프로그래밍 방식으로 등록된 BeanPostProcessor 인스턴스는 명시적인 순서에 관계없이 자동 감지를 통해 등록된 인스턴스보다 항상 먼저 처리된다는 점에 유의하세요.
BeanPostProcessor 인스턴스 및 AOP 자동 프록싱

BeanPostProcessor 인터페이스를 구현하는 클래스는 특별하며 컨테이너에서 다르게 취급됩니다. 모든 BeanPostProcessor 인스턴스와 이들이 직접 참조하는 Bean은 시작 시 ApplicationContext 의 특수 시작 단계의 일부로 인스턴스화됩니다. 그 다음, 모든 BeanPostProcessor 인스턴스가 정렬된 방식으로 등록되고 컨테이너의 모든 추가 Bean에 적용됩니다. AOP 자동 프록시는 BeanPostProcessor 자체로 구현되기 때문에 BeanPostProcessor 인스턴스나 인스턴스가 직접 참조하는 Bean은 자동 프록시를 사용할 수 없으며 따라서 측면이 짜여져 있지 않습니다.

이러한 Bean의 경우 정보 로그 메시지가 표시되어야 합니다: 일부 Bean은 모든 BeanPostProcessor 인터페이스에서 처리할 수 없습니다(예: 자동 프록시에 적합하지 않음).

자동 배선 또는 @Resource (자동 배선으로 되돌아갈 수 있음)를 사용하여 BeanPostProcessor 에 Bean을 연결한 경우 Spring이 유형 일치 종속성 후보를 검색할 때 예기치 않은 Bean에 액세스하여 자동 프록시 또는 다른 종류의 Bean 사후 처리에 부적합하게 만들 수 있습니다. 예를 들어, 필드 또는 설정자 이름이 선언된 Bean의 이름과 직접 일치하지 않고 이름 속성이 사용되지 않는 @Resource 로 주석이 달린 종속성이 있는 경우, Spring은 유형별로 일치시키기 위해 다른 Bean에 액세스합니다.

The following examples show how to write, register, and use BeanPostProcessor instances in an ApplicationContext.

Example: Hello World, BeanPostProcessor-style

이 첫 번째 예제는 기본적인 사용법을 보여줍니다. 이 예는 컨테이너에서 생성될 때 각 Bean의 toString() 메서드를 호출하고 결과 문자열을 시스템 콘솔에 인쇄하는 사용자 지정 BeanPostProcessor 구현을 보여줍니다.

다음 목록은 사용자 지정 BeanPostProcessor 구현 클래스 정의를 보여줍니다:

  • Java

  • Kotlin

package scripting;

import org.springframework.beans.factory.config.BeanPostProcessor;

public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {

	// simply return the instantiated bean as-is
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean; // we could potentially return any object reference here...
	}

	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("Bean '" + beanName + "' created : " + bean.toString());
		return bean;
	}
}
package scripting

import org.springframework.beans.factory.config.BeanPostProcessor

class InstantiationTracingBeanPostProcessor : BeanPostProcessor {

	// simply return the instantiated bean as-is
	override fun postProcessBeforeInitialization(bean: Any, beanName: String): Any? {
		return bean // we could potentially return any object reference here...
	}

	override fun postProcessAfterInitialization(bean: Any, beanName: String): Any? {
		println("Bean '$beanName' created : $bean")
		return bean
	}
}

다음 beans 요소는 InstantiationTracingBeanPostProcessor 를 사용합니다:

<?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:lang="http://www.springframework.org/schema/lang"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/lang
		https://www.springframework.org/schema/lang/spring-lang.xsd">

	<lang:groovy id="messenger"
			script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
		<lang:property name="message" value="Fiona Apple Is Just So Dreamy."/>
	</lang:groovy>

	<!--
	when the above bean (messenger) is instantiated, this custom
	BeanPostProcessor implementation will output the fact to the system console
	-->
	<bean class="scripting.InstantiationTracingBeanPostProcessor"/>

</beans>

InstantiationTracingBeanPostProcessor 가 어떻게 정의되어 있는지 주목하세요. 이름도 없으며, Bean이기 때문에 다른 Bean과 마찬가지로 종속성을 주입할 수 있습니다. (앞의 구성은 Groovy 스크립트에 의해 뒷받침되는 Bean도 정의합니다. Spring 동적 언어 지원은 동적 언어 지원이라는 장에 자세히 설명되어 있습니다).

다음 Java 애플리케이션은 앞의 코드와 구성을 실행합니다:

  • Java

  • Kotlin

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scripting.Messenger;

public final class Boot {

	public static void main(final String[] args) throws Exception {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
		Messenger messenger = ctx.getBean("messenger", Messenger.class);
		System.out.println(messenger);
	}

}
   import org.springframework.beans.factory.getBean

fun main() {
	val ctx = ClassPathXmlApplicationContext("scripting/beans.xml")
	val messenger = ctx.getBean<Messenger>("messenger")
	println(messenger)
}

The output of the preceding application resembles the following:

Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
org.springframework.scripting.groovy.GroovyMessenger@272961

Example: The AutowiredAnnotationBeanPostProcessor

콜백 인터페이스 또는 어노테이션을 사용자 정의 BeanPostProcessor 구현과 함께 사용하는 것은 Spring IoC 컨테이너를 확장하는 일반적인 수단입니다. 예를 들어 Spring 배포와 함께 제공되며 주석이 달린 필드, 설정자 메서드 및 임의의 구성 메서드를 Autowiring하는 BeanPostProcessor 구현인 Spring의 AutowiredAnnotationBeanPostProcessor 를 들 수 있습니다.

BeanFactoryPostProcessor 로 구성 메타데이터 커스터마이징하기(Customizing Configuration Metadata with a BeanFactoryPostProcessor)

다음으로 살펴볼 확장 포인트는 org.springframework.beans.factory.config.BeanFactoryPostProcessor 입니다. 이 인터페이스의 의미는 한 가지 큰 차이점이 있지만 BeanPostProcessor 인터페이스의 의미와 유사합니다: BeanFactoryPostProcessor 는 Bean 구성 메타데이터에서 작동합니다. 즉, Spring IoC 컨테이너는 BeanFactoryPostProcessor 가 구성 메타데이터를 읽고 컨테이너가 BeanFactoryPostProcessor 인스턴스 이외의 Bean을 인스턴스화하기 전에 잠재적으로 변경할 수 있게 해줍니다.

여러 개의 BeanFactoryPostProcessor 인스턴스를 구성할 수 있으며, order 속성을 설정하여 이러한 BeanFactoryPostProcessor 인스턴스가 실행되는 순서를 제어할 수 있습니다. 그러나 이 property는 BeanFactoryPostProcessorOrdered 인터페이스를 구현하는 경우에만 설정할 수 있습니다. 자체 BeanFactoryPostProcessor 를 작성하는 경우 Ordered 인터페이스도 구현하는 것을 고려해야 합니다. 자세한 내용은 BeanFactoryPostProcessorOrdered 인터페이스의 javadoc을 참조하세요.

실제 Bean 인스턴스(즉, 구성 메타데이터에서 생성되는 객체)를 변경하려면 대신 BeanPostProcessor 를 사용해야 합니다(앞의 BeanPostProcessor 를 사용하여 Bean 사용자 정의에 설명되어 있습니다). 예를 들어, BeanFactory.getBean() 을 사용하여 BeanFactoryPostProcessor 내에서 Bean 인스턴스로 작업하는 것은 기술적으로 가능하지만, 그렇게 하면 표준 컨테이너 수명 주기를 위반하여 조기 Bean 인스턴스화가 발생합니다. 이로 인해 Bean 사후 처리를 우회하는 등의 부작용이 발생할 수 있습니다.

또한 BeanFactoryPostProcessor 인스턴스는 컨테이너별로 Scope가 지정됩니다. 이는 컨테이너 계층 구조를 사용하는 경우에만 관련이 있습니다. 하나의 컨테이너에 BeanFactoryPostProcessor 를 정의하면 해당 컨테이너의 Bean 정의에만 적용됩니다. 두 컨테이너가 동일한 계층에 속해 있더라도 한 컨테이너의 Bean 정의는 다른 컨테이너의 BeanFactoryPostProcessor 인스턴스에 의해 사후 처리되지 않습니다.

컨테이너를 정의하는 구성 메타데이터에 변경 사항을 적용하기 위해 ApplicationContext 내부에 선언되면 Bean 팩토리 post-processor가 자동으로 실행됩니다. Spring에는 PropertyOverrideConfigurer 및 `PropertySourcesPlaceholderConfigurer`와 같이 미리 정의된 여러 Bean 팩토리 post-processor가 포함되어 있습니다. 사용자 정의 `BeanFactoryPostProcessor`를 사용할 수도 있습니다. — 예를 들어 사용자 정의 속성 편집기를 등록할 수도 있습니다.

ApplicationContextBeanFactoryPostProcessor 인터페이스를 구현하는 배포된 모든 Bean을 자동으로 감지합니다. 그리고 적절한 시점에 이러한 Bean을 Bean Factory post-processor로 사용합니다. 다른 Bean과 마찬가지로 이러한 post-processor Bean을 배포할 수 있습니다.

BeanPostProcessor 와 마찬가지로 일반적으로 지연 초기화를 위해 BeanFactoryPostProcessor 를 구성하고 싶지 않을 것입니다. 다른 Bean이 Bean(Factory)PostProcessor 를 참조하지 않으면 해당 post-processor는 전혀 인스턴스화되지 않습니다. 따라서 지연 초기화를 위해 표시하는 것은 무시되며, <beans /> 요소의 선언에서 default-lazy-init 속성을 true 로 설정하더라도 Bean(Factory)PostProcessor 는 열심히 인스턴스화됩니다.

Example: The Class Name Substitution PropertySourcesPlaceholderConfigurer

표준 Java Properties 형식을 사용하여 별도의 파일에 있는 Bean 정의의 property 값을 외부화하기 위해 PropertySourcesPlaceholderConfigurer 를 사용할 수 있습니다. 이렇게 하면 애플리케이션을 배포하는 사람이 컨테이너의 기본 XML 정의 파일을 수정해야 하는 복잡성이나 위험 없이 데이터베이스 URL 및 비밀번호와 같은 환경별 속성을 사용자 정의할 수 있습니다.

플레이스홀더 값을 가진 DataSource 가 정의된 다음 XML 기반 구성 메타데이터 조각을 살펴보세요:

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
	<property name="locations" value="classpath:com/something/jdbc.properties"/>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="${jdbc.driverClassName}"/>
	<property name="url" value="${jdbc.url}"/>
	<property name="username" value="${jdbc.username}"/>
	<property name="password" value="${jdbc.password}"/>
</bean>

이 예는 외부 Properties 파일에서 구성된 속성을 보여줍니다. 런타임에 데이터 소스의 일부 property를 대체하는 메타데이터에 PropertySourcesPlaceholderConfigurer 가 적용됩니다. 대체할 값은 Ant와 log4j 및 JSP EL 스타일을 따르는 ${property-name} 형식의 플레이스홀더로 지정됩니다.

실제 값은 표준 Java properties 형식의 다른 파일에서 가져옵니다:

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root

따라서 ${jdbc.username} 문자열은 런타임에 'sa' 라는 값으로 대체되며, 속성 파일의 키와 일치하는 다른 자리 표시자 값에도 동일하게 적용됩니다. PropertySourcesPlaceholderConfigurer 는 Bean 정의의 대부분의 property 및 속성에서 플레이스홀더를 확인합니다. 또한 플레이스홀더 접두사와 접미사를 사용자 지정할 수 있습니다.

Spring 2.5에 도입된 context 네임스페이스를 사용하면 전용 구성 요소로 property 플레이스홀더를 구성할 수 있습니다. 다음 예제와 같이 location 속성에 하나 이상의 위치를 쉼표로 구분된 목록으로 제공할 수 있습니다:

<context:property-placeholder location="classpath:com/something/jdbc.properties"/>

PropertySourcesPlaceholderConfigurer 는 사용자가 지정한 Properties 파일에서 속성만 찾는 것이 아닙니다. 기본적으로 지정된 속성 파일에서 속성을 찾을 수 없는 경우 Spring Environment 속성 및 일반 Java System 속성에 대해 검사합니다.

이러한 요소는 해당 애플리케이션에 필요한 속성을 가진 하나의 요소만 정의해야 합니다. 고유한 플레이스홀더 구문(${…​})을 사용하는 한 여러 개의 속성 플레이스홀더를 구성할 수 있습니다.

대체에 사용되는 속성 소스를 모듈화해야 하는 경우 여러 속성 자리 표시자를 생성해서는 안 됩니다. 그 대신 사용할 속성을 수집하는 자체 PropertySourcesPlaceholderConfigurer Bean을 만들어야 합니다.

PropertySourcesPlaceholderConfigurer 를 사용하여 클래스 이름을 대체할 수 있는데, 이는 런타임에 특정 구현 클래스를 선택해야 할 때 유용할 때가 있습니다. 다음 예제는 그 방법을 보여줍니다:

<bean class="org.springframework.beans.factory.config.PropertySourcesPlaceholderConfigurer">
	<property name="locations">
		<value>classpath:com/something/strategy.properties</value>
	</property>
	<property name="properties">
		<value>custom.strategy.class=com.something.DefaultStrategy</value>
	</property>
</bean>

<bean id="serviceStrategy" class="${custom.strategy.class}"/>

런타임에 클래스를 유효한 클래스로 확인할 수 없는 경우, Bean이 생성되려고 할 때, 즉 지연 초기화되지 않은 Bean에 대한 ApplicationContext`의 `preInstantiateSingletons() 단계 중에 Bean의 (해결?)resolution이 실패합니다.

Example: The PropertyOverrideConfigurer

또 다른 Bean 팩토리 사후 처리기인 PropertyOverrideConfigurerPropertySourcesPlaceholderConfigurer 와 유사하지만, 후자와 달리 원래 정의에 Bean 속성에 대한 기본값이 있거나 값이 전혀 없을 수 있습니다. 재정의된 Properties 파일에 특정 Bean 속성에 대한 항목이 없는 경우 기본 컨텍스트 정의가 사용됩니다.

Bean 정의는 재정의되고 있다는 것을 인식하지 못하므로 XML 정의 파일에서 재정의 구성자가 사용되고 있다는 것을 즉시 알 수 없습니다. 동일한 Bean 속성에 대해 서로 다른 값을 정의하는 여러 개의 PropertyOverrideConfigurer 인스턴스가 있는 경우, 재정의 메커니즘으로 인해 마지막 인스턴스가 승리합니다.

속성 파일 구성 줄의 형식은 다음과 같습니다:

beanName.property=value

The following listing shows an example of the format:

dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb

이 예제 파일은 driverurl 속성을 가진 dataSource 라는 Bean을 포함하는 컨테이너 정의와 함께 사용할 수 있습니다.

재정의되는 최종 속성을 제외한 경로의 모든 구성 요소가 이미 null이 아닌 경우(아마도 생성자에 의해 초기화되었을 것입니다) 복합 속성 이름도 지원됩니다. 다음 예제에서는 tom Bean의 fred 속성의 bob 속성의 sammy 속성이 스칼라 값 123 으로 설정되어 있습니다:

tom.fred.bob.sammy=123
지정된 재정의 값은 항상 리터럴 값입니다. 이 값은 Bean 참조로 변환되지 않습니다. 이 규칙은 XML Bean의 원래 값이 정의의 원래 값이 Bean 참조를 지정하는 경우에도 적용됩니다.

Spring 2.5에 도입된 context 네임스페이스를 사용하면 전용 구성을 사용하여 property를 전용 구성 요소로 재정의할 수 있습니다:

<context:property-override location="classpath:override.properties"/>

FactoryBean`으로 인스턴스화 로직 커스터마이징하기(Customizing Instantiation Logic with a `FactoryBean)

그 자체로 팩토리인 객체에 대해 org.springframework.beans.factory.FactoryBean 인터페이스를 구현할 수 있습니다.

FactoryBean 인터페이스는 Spring IoC 컨테이너의 인스턴스화 로직에 플러그할 수 있는 지점입니다. (잠재적으로) 장황한 양의 XML 대신 Java로 더 잘 표현되는 복잡한 초기화 코드가 있는 경우, 자체 FactoryBean 을 생성하고 해당 클래스 내에서 복잡한 초기화를 작성한 다음 사용자 정의 FactoryBean 을 컨테이너에 연결할 수 있습니다.

FactoryBean<T> 인터페이스는 세 가지 메서드를 제공합니다:

  • T getObject(): 이 팩토리가 생성하는 객체의 인스턴스를 반환합니다. 이 팩토리가 싱글톤을 반환하는지 아니면 프로토타입을 반환하는지에 따라 인스턴스를 공유할 수 있습니다.

  • boolean isSingleton(): 이 FactoryBean 이 싱글톤을 반환하면 true 를 리턴하고, 그렇지 않으면 false 를 리턴합니다. 이 메서드의 기본 구현은 true 를 반환합니다.

  • Class<?> getObjectType(): getObject()` 메서드가 반환한 객체 타입을 반환하거나, 타입을 미리 알 수 없는 경우 null 을 반환합니다.

FactoryBean 개념과 인터페이스는 Spring 프레임워크 내 여러 곳에서 사용됩니다. 50개 이상의 FactoryBean 인터페이스 구현이 Spring 자체와 함께 제공됩니다.

컨테이너가 생성하는 Bean 대신 실제 FactoryBean 인스턴스 자체를 컨테이너에 요청해야 하는 경우, ApplicationContextgetBean() 메서드를 호출할 때 Bean의 id 앞에 앰퍼샌드 기호(&)를 붙이면 됩니다. 따라서 idmyBean 인 주어진 FactoryBean`의 경우 컨테이너에서 `getBean("myBean") 을 호출하면 FactoryBean 의 생성물이 반환되는 반면, getBean("&myBean") 을 호출하면 FactoryBean 인스턴스 자체가 반환됩니다.