Whiteship's Note


Bean Life Cycle

Spring/Chapter 3 : 2007.06.21 13:48


사용자 삽입 이미지

<참조>
Spring In Action 48쪽
[Spring 3] BeanFactory와 ApplicationContext 내의 Bean의 Lifecycle
Spring API :: BeanFactory
신고
top


Vlidator - Property 파일 사용하기



이전 글에서 사용한 방법으로는 입력 필드에 값이 비어있는지만 확인할 수 있습니다. 아마도 Errors 객체를 사용할 때 값이 비어있는지 검사하려면 if 문이 자주 사용되니까 그 코드를 줄여주기 위해 만든것 같습니다.

따라서 빈 값인지 확인할 때는 유용하게 사용할 수 있지만 그 이외의 경우에는 Errors 인터페이스를 사용해야 한다.
사용자 삽입 이미지
Errors의 인터페이스 중에 에러 메시지를 기록할 수 있는 메소드들입니다.

인자의 종류를 살펴보면 다음과 같습니다.
field :: 에러 메시지를 남길 대상이 되는 필드
errorCode :: 프로퍼티 파일에 있는 에러 메시지의 이름(키)
errorAgs :: 프로퍼티 파일에 있는 에러 메시지의 내용(값)을 출력할 때 특정 문자열을 넘겨 줄 수 있습니다. 그 때 이 아규먼트를 사용합니다.
defaultMessage :: 프로퍼티 파일에서 errorCode에 해당하는 메시지 키를 못찾으면 여기에 입력한 값을 출력합니다.


프로퍼티 파일을 사용하는 방법은 간단합니다.
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="message" />
    </bean>

위와 같이 messageSource를 등록합니다. 이 때 프로퍼티 파일의 이름을 basename에 입력해 줍니다. 만약 프로퍼티 파일이 여러개라면 besenames 속성을 사용하여 다음과 같이 list로 넘겨줍니다.

<beans>
  <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
      <list>
        <value>format</value>
        <value>exceptions</value>
        <value>windows</value>
      </list>
    </property>
  </bean>
</beans>

그 다음 프로퍼티 파일을 작성합니다. 위 설정에서 message 라는 이름을 입력했으니까 프로퍼티 파일은 message.properties 또는 message_ko_KR.properties 이런식으로 입력값 뒤에 지역코드가 붙은 프로퍼티 파일도 자동으로 읽히게 됩니다.

required=Input {0} Properties
passwordTooShort=Enter password at least 6 characters.
notSamePassword=Enter the same vlaue with password


프로퍼티에 저렇게 내용을 채우고 이제는 Validator를 만듭니다. 저번에 만든 코드에서 살짝 내용을 추가/수정했습니다.

public class MemberInfoValidator implements Validator{

    public boolean supports(Class clazz) {
        return MemberInfo.class.isAssignableFrom(clazz);
    }

    public void validate(Object object, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "required", new Object [] {"email"}, "Enter your email");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "required", new Object [] {"password"}, "Enter your password");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmPassword", "required", new Object [] {"confirmPassword"}, "Enter the same password for confirmation");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmMember", "required", new Object [] {"confirmMember"}, "Enter ajn member code");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required", new Object [] {"name"}, "Enter your name");

        MemberInfo memberInfo = (MemberInfo)object;
        if(memberInfo.getPassword().length() < 6)
            errors.rejectValue("password", "passwordTooShort");

        if(!memberInfo.getPassword().equals(memberInfo.getConfirmPassword()))
            errors.rejectValue("confirmPassword", "notSamePassword");
    }

}

이제 실행해보면 다음과 같이 에러메시지들이 출력됩니다.
사용자 삽입 이미지


신고
top


Bean Life Cycle 콜백 인터페이스 사용 예(in Spring)

Spring/Chapter 3 : 2007.05.11 11:54


BeanNameAware
- ServletForwardingController
- AbstractView
- PortletWrappingController
- GenericFilterBean
- JobDetailBean
- OsgiServiceProxyFactoryBean
- AbstractTest
- EhCacheFactoryBean
- FieldRetrievingFactoryBean

BeanClassLoaderAware
- 구현 방법 : this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
- AbstractBeanFactory
- AbstractBeanDefinitionReader ::
- ConfigurableBeanFactory 인터페이스 ::
- AbstractHttpInvokerRequestExecutor
- HttpInvokerTests

BeanFactoryAware
- MethodLocatingFactoryBean
- ProxyFactoryBean
= AbstractAdvisorAutoProxyCreator
- AbstractBeanFactoryBasedTargetSourceCreator
- ScopedProxyFactoryBean
- AbstractBeanFactoryBasedTargetSource
- AutowiredAnnotationBeanPostProcessor
- ObjectFactoryCreatingFactoryBean
- ServiceLocatorFactoryBean
- DependencyInjectionAspectSupport
- 엄청난 분량

BeanPostProcessor :: before :: after
- BundleContextAwareProcessor :: 해당 bean이 bundleaware 일 때 BundleContext 세팅, 로깅, 없으면 예외처리 :: ::
- CommonsLogProviderBeanPostProcessor :: 리플렉션 사용해서 로깅 :: ::
- ServletContextAwareProcessor :: ServletContext랑 SevletConfig 세팅 :: ::
- PortletContextAwareProcessor
- AbstractAutoProxyCreator ::  :: 프록시 만들 때 사용

InitializingBean
- MustBeInitialized
- ServiceCreationFactoryBean
- CommonsLogFactoryBean :: 로깅
- FieldRetrievingFactoryBean :: 없으면 확인하고
- MethodInvokingFactoryBean ::
public void afterPropertiesSet() throws Exception {
        prepare();
        if (this.singleton) {
            this.initialized = true;
            this.singletonObject = doInvoke();
        }
    }
- PropertiesFactoryBean :: 싱글톤인지..
- ResourceFactoryBean :: resource 가 널이면 예외 발생
- 그 외에도 많아요.

ResourceLoaderAware
- ReloadableResourceBundleMessageSource :: Set the ResourceLoader to use for loading bundle properties files.
- DefaultPersistenceUnitManager
- ResourceJobSchedulingDataProcessor
- ScriptFactoryPostProcessor

ApplicationEventPublisherAware
- EventPublicationInterceptor :: invoke 호출할 때 이벤트 발생

MessageSourceAware
- Service :: 그냥 구현했네

ApplicationContextAware
- ApplicationObjectSupport :: applicationcontext 세팅하고 주는일 하는데 사용하는거 편하게 해주려고 만든 클레스
- SchedulerFactoryBean :: 스케쥴링 할 때 applicatoincontext 사용

ServletContextAware
-ServletContextAwareBean :: 기본 구현
- ServletContextAttributeExporter :: servletcontext 받아서 attributes Map을 채우네..
- ServletContextAttributeFactoryBean :: 위랑 같은데 역긴 attribute 하나만 채우네..
- ServletContextFactoryBean :: 기본 구현
- ServletContextParameterFactoryBean :: this.paramValue = servletContext.getInitParameter(this.initParamName); paramValue 세팅
- ServletContextPropertyPlaceholderConfigurer :: resolvePlaceholder 에서 사용
- WebApplicationObjectSupport :: 기본 구현
- CommonsMultipartResolver :: FileItemFactor에 Repository 위치 정보 세팅
- SimpleServletPostProcessor :: postProcessAfterInitialization 에서 사용
신고

'Spring > Chapter 3' 카테고리의 다른 글

3.10.1. @Autowired  (0) 2007.07.30
3.10. Annotation-based configuration  (0) 2007.07.30
Bean Life Cycle  (2) 2007.06.21
Spring에서 Bean을 언제 만들지?  (5) 2007.06.05
Spring Reference 3장 오타  (2) 2007.05.22
Bean Life Cycle 콜백 인터페이스 사용 예(in Spring)  (2) 2007.05.11
머리 뽀개지는 BeanPostProcessor  (0) 2007.05.09
Bean Life Cycle 통째로 테스트  (0) 2007.05.09
BeanFactoryAware 테스트  (0) 2007.05.09
BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
top


머리 뽀개지는 BeanPostProcessor

Spring/Chapter 3 : 2007.05.09 17:20


이전 글에서 모든 Bean Life Cycle 콜백들을 구현하여 모든 콜백들이 예상대로 동작하는지 확인해봤습니다. 모든 메소드들이 제대로 동작했지만 BeanPostProcessor만 이상하게 동작하지 않았습니다.

결론부터 말씀드리면 재미없기 때문에 일단 코드를 보겠습니다.
    <bean id="test" class="net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean" init-method="customInit" />

    <bean id="test2" class="net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean" init-method="customInit" />

이 전 글에서 테스트 할 때 사용한 클레스를 다른 빈으로 하나 더 등록하고 테스트를 돌렸습니다.

setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.
setResourceLoader() 실행합니다.
setApplicationEventPublisher() 실행합니다.
setMessageSource() 실행합니다.
setApplicationContext() 실행합니다.
afterPropertiesSet() 실행합니다.
customInit() 실행합니다.
setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.
setResourceLoader() 실행합니다.
setApplicationEventPublisher() 실행합니다.
setMessageSource() 실행합니다.
setApplicationContext() 실행합니다.
postProcessBeforeInitialization() 실행합니다.
afterPropertiesSet() 실행합니다.
customInit() 실행합니다.
postProcessAfterInitialization() 실행합니다.

자 이제 수수께기가 풀리기 시작합니다. 제가 녹색으로 칠한 부분이 test 빈에서 찍힌것이고 v하늘색은 test1 빈에서 찍힌것입니다.

BeanPostProcessor의 콜백 메소드들은 자신 이후에 생성되는 빈들에 적용됩니다.

좀 더 확실하게 확인하기 위해서 이번엔 세 개로 테스트 해보겠습니다.

    <bean id="test" class="net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean" init-method="customInit" />

    <bean id="test2" class="net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean" init-method="customInit" />

    <bean id="test3" class="net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean" init-method="customInit" />

결과는 다음과 같습니다,

setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.
setResourceLoader() 실행합니다.
setApplicationEventPublisher() 실행합니다.
setMessageSource() 실행합니다.
setApplicationContext() 실행합니다.
afterPropertiesSet() 실행합니다.
customInit() 실행합니다.
setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.
setResourceLoader() 실행합니다.
setApplicationEventPublisher() 실행합니다.
setMessageSource() 실행합니다.
setApplicationContext() 실행합니다.
postProcessBeforeInitialization() 실행합니다.
afterPropertiesSet() 실행합니다.
customInit() 실행합니다.
postProcessAfterInitialization() 실행합니다.
setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.
setResourceLoader() 실행합니다.
setApplicationEventPublisher() 실행합니다.
setMessageSource() 실행합니다.
setApplicationContext() 실행합니다.
postProcessBeforeInitialization() 실행합니다.
postProcessBeforeInitialization() 실행합니다.
afterPropertiesSet() 실행합니다.
customInit() 실행합니다.
postProcessAfterInitialization() 실행합니다.
postProcessAfterInitialization() 실행합니다.

하지만 bean 생성은 보통 설정 파일에 등록되어 있는 순서이고 depends-on 속성을 사용한다 하더라고 위 처럼 여러개의 BeanPostProcessor의 실행 순서를 예측하기란 사실 불안합니다.

그래서...BeanPostProcessor가 implements하고 있는 Orderd 인터페이스를 사용하여 순서를 지정할 수 있습니다.

BeanFactoryPostProcessor와의 차이는 BeanPostProcessor는 Bean 객체에 조작을 하는 반명 BeanFactoyPostProcessor는 Bean을 만드는 설명서에 해당하는 설정파일을 조작한다는 것입니다.
신고

'Spring > Chapter 3' 카테고리의 다른 글

3.10. Annotation-based configuration  (0) 2007.07.30
Bean Life Cycle  (2) 2007.06.21
Spring에서 Bean을 언제 만들지?  (5) 2007.06.05
Spring Reference 3장 오타  (2) 2007.05.22
Bean Life Cycle 콜백 인터페이스 사용 예(in Spring)  (2) 2007.05.11
머리 뽀개지는 BeanPostProcessor  (0) 2007.05.09
Bean Life Cycle 통째로 테스트  (0) 2007.05.09
BeanFactoryAware 테스트  (0) 2007.05.09
BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
3.4.3. The other scopes  (6) 2007.04.29
top


Bean Life Cycle 통째로 테스트

Spring/Chapter 3 : 2007.05.09 17:02


Bean Life Cycle
BeanNameAware 테스트
BeanClassLoaderAware 테스트
BeanFactoryAware 테스트
MessageSource 사용 예
ApplicationEvent 사용 예
MessageSource 사용 예
BeanPostProcessor 사용 예

다 비슷한 테스트 들인데 하나씩 테스트 하기가 지겨워서 Bean Life Cycle에 관여하는 모든 인터페이스를 전부 구현하도록 했습니다.

/**
 *
 */
package net.agilejava.jedi.spring.beanLifeCycle;

import javax.servlet.ServletContext;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.context.ServletContextAware;

/**
 * @author keesun
 *
 */
public class BeanLifeCycleTestBean implements BeanNameAware,
    BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware,
    ApplicationEventPublisherAware, MessageSourceAware,
    ApplicationContextAware, ServletContextAware, BeanPostProcessor,
    InitializingBean{

    String beanName;

    ClassLoader classLoader;

    BeanFactory beanFactory;

    ResourceLoader resourceLoader;

    public void setBeanName(String beanName) {
        System.out.println("setBeanName() 실행합니다.");
        this.beanName = beanName;
    }

    public String getBeanName(){
        return beanName;
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("setBeanClassLoader() 실행합니다.");
        this.classLoader = classLoader;
    }

    public ClassLoader getClassLoader() {
        return classLoader;
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory() 실행합니다.");
        this.beanFactory = beanFactory;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("setResourceLoader() 실행합니다.");
        this.resourceLoader = resourceLoader;
    }

    public ResourceLoader getResourceLoader(){
        return resourceLoader;
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher arg0) {
        System.out.println("setApplicationEventPublisher() 실행합니다.");
    }

    public void setMessageSource(MessageSource arg0) {
        System.out.println("setMessageSource() 실행합니다.");
    }

    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        System.out.println("setApplicationContext() 실행합니다.");
    }

    public void setServletContext(ServletContext servletContext){
        System.out.println("setServletContext() 실행합니다.");
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization() 실행합니다.");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization() 실행합니다.");
        return bean;
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet() 실행합니다.");
    }

    public void customInit(){
        System.out.println("customInit() 실행합니다.");
    }
}

테스트에서는 getBean으로 해당 bean을 가져오기만 합니다. 그러면 다음과 같은 출력을 확인할 수 있습니다.

setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.
setResourceLoader() 실행합니다.
setApplicationEventPublisher() 실행합니다.
setMessageSource() 실행합니다.
setApplicationContext() 실행합니다.
afterPropertiesSet() 실행합니다.
customInit() 실행합니다.

어라.. 뭔가 빠졌습니다. 뭐가 빠졌을까요.. 구현한 것 중에 BeanPostProcessor와 관련된 callback들이 실행되지 않았습니다.

이론~ 왜이러는거야~~ 왜 BeanPostProcessor를 왕따시키는거야!!
신고

'Spring > Chapter 3' 카테고리의 다른 글

Bean Life Cycle  (2) 2007.06.21
Spring에서 Bean을 언제 만들지?  (5) 2007.06.05
Spring Reference 3장 오타  (2) 2007.05.22
Bean Life Cycle 콜백 인터페이스 사용 예(in Spring)  (2) 2007.05.11
머리 뽀개지는 BeanPostProcessor  (0) 2007.05.09
Bean Life Cycle 통째로 테스트  (0) 2007.05.09
BeanFactoryAware 테스트  (0) 2007.05.09
BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
3.4.3. The other scopes  (6) 2007.04.29
Circular dependencies  (0) 2007.03.24
top


BeanFactoryAware 테스트

Spring/Chapter 3 : 2007.05.09 15:34


    @Test
    public void testBeanFactoryAware() {
        BeanFactory beanFactory = bean.getBeanFactory();
        assertNotNull(beanFactory);
    }

테스트 코드는 간단합니다. 이전 글에 사용했던 클레스에 BeanFactoryAware 인터페이스를 추가로 구현합니다.

public class BeanLifeCycleTestBean implements BeanFactoryAware, ... {

    ... 생략

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory() 실행합니다.");
        this.beanFactory = beanFactory;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

}

테스트를 실행하면 테스트가 통과 하는 걸 확인 할 수 있습니다. 그리고 Output 창을 통해 확인 하면 다음과 같습니다.

setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.

BeanFactoryAware 사용 예
ObjectFactoryCreatingFactoryBean 사용 예

이 인터페이스를 구현한 클레스들..
AbstractAdvisorAutoProxyCreator, AbstractAutoProxyCreator, AbstractBeanFactoryBasedTargetSource, AbstractBeanFactoryBasedTargetSourceCreator, AbstractBeanFactoryPointcutAdvisor, AbstractFactoryBean, AbstractPoolingTargetSource, AbstractPrototypeBasedTargetSource, AnnotationAwareAspectJAutoProxyCreator, AspectJAwareAdvisorAutoProxyCreator, BeanConfigurerSupport, BeanFactoryDataSourceLookup, BeanNameAutoProxyCreator, BeanReferenceFactoryBean, CommonsPoolTargetSource, DefaultAdvisorAutoProxyCreator, DefaultBeanFactoryPointcutAdvisor, HibernateAccessor, HibernateAccessor, HibernateInterceptor, HibernateInterceptor, HibernateTemplate, HibernateTemplate, HibernateTransactionManager, HibernateTransactionManager, LazyInitTargetSource, LazyInitTargetSourceCreator, ListFactoryBean, MapFactoryBean, MBeanExporter, MethodInvokingFactoryBean, MethodInvokingJobDetailFactoryBean, MethodLocatingFactoryBean, ObjectFactoryCreatingFactoryBean, OpenSessionInViewInterceptor, OpenSessionInViewInterceptor, PersistenceAnnotationBeanPostProcessor, PersistenceExceptionTranslationInterceptor, PersistenceExceptionTranslationPostProcessor, PreferencesPlaceholderConfigurer, PropertyPathFactoryBean, PropertyPlaceholderConfigurer, PrototypeTargetSource, ProxyFactoryBean, QuickTargetSourceCreator, ScopedProxyFactoryBean, ScriptFactoryPostProcessor, ServiceLocatorFactoryBean, ServletContextPropertyPlaceholderConfigurer, SetFactoryBean, SimpleBeanFactoryAwareAspectInstanceFactory, SimpleBeanTargetSource, ThreadLocalTargetSource, TransactionProxyFactoryBean
엄청나게 많습니다.

주로 다른 Bean을 lock up 할 수 있는 factory사 필요할 때 사용합니다. 특정 객체만을 뽑아낼 factory가 필요하다면 FactoryBean을 사용하면 되는데 이때도 이 인터페이스를 사용할 수 있기 때문에 위의 구현체들의 반정도는 XXXFactoryBean 입니다.

FactroyBean을 사용하는 이유는 '만들 수 없는 것'을 FactoryBean으로 만들기 이 글에서 확인할 수 있으며 주로 객체 생성에 복잡한 설정과 로직이 필요한 경우에 사용하며 따라서 다른 프레임워크와 연동하는 객체가 필요한 경우에 자주 사용하며 위의 구현체 중에 또 절반 정도는 그러한 구현체에 해당합니다.


신고
top


BeanClassLoaderAware 테스트

Spring/Chapter 3 : 2007.05.09 08:32


이전 글에서 사용한 Bean 클레스에 BeanClassLoaderAware 인터페이스를 추가로 구현합니다.
public class BeanLifeCycleTestBean implements BeanNameAware, BeanClassLoaderAware{

    String beanName;

    ClassLoader classLoader;

    public void setBeanName(String beanName) {
        System.out.println("setBeanName() 실행합니다.");
        this.beanName = beanName;
    }

    public String getBeanName(){
        return beanName;
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("setBeanClassLoader() 실행합니다.");
        this.classLoader = classLoader;
    }

    public ClassLoader getClassLoader() {
        return classLoader;
    }

간단한 로깅을 위해서 문자열을 출력해 줍니다. 빈 설정은 바뀔 것이 없으며 테스트 코드만 약간 변경합니다.
public class BeanLifeCycleTest {

    private ApplicationContext context;
    private BeanLifeCycleTestBean bean;

    @Before
    public void setUp(){
        context = new ClassPathXmlApplicationContext("net/agilejava/jedi/spring/beanLifeCycle/applicationContext.xml");
        bean = (BeanLifeCycleTestBean) context.getBean("test");
    }

    @Test
    public void testBeanNameAware() {
        assertEquals("test", bean.getBeanName());
    }

    @Test
    public void testClassLoaderAware() {
        ClassLoader classLoader = bean.getClassLoader();
        assertNotNull(classLoader);
    }

}

Spring 소스코드에서 BeanClassLoader 인터페이스를 구현한 클레스들입니다.
- AbstractBeanFactory :: configurableBeanFactory 인터페이스 구현체
- AbstractBeanDefinitionReader :: Set the ClassLoader to use for bean classes. Default is null, which suggests to not load bean classes eagerly but rather to just register bean definitions with class names, with the corresponding Classes to be resolved later (or never).
- ConfigurableBeanFactory 인터페이스 :: Set the class loader to use for loading bean classes. Default is the thread context class loader. Note that this class loader will only apply to bean definitions that do not carry a resolved bean class yet. This is the case as of Spring 2.0 by default: Bean definitions only carry bean class names, to be resolved once the factory processes the bean definition.
- AbstractHttpInvokerRequestExecutor
- HttpInvokerTests
This is mainly intended to be implemented by framework classes which have to pick up application classes by name despite themselves potentially being loaded from a shared class loader.
ClassLoader 에 대한 학습이 필요하겠군요. 얼추 보니까 loadClass("풀 패키지 이름 붙은 클레스명") 을 사용하여 Class 객체를 받아 올 수 있습니다. 그 이후에는 리플렉션으로 이어지겠군요.

ClassLoader를 테스트 하기 위해 테스트 코드를 약간 수정했습니다.
    @Test
    public void testClassLoaderAware() throws ClassNotFoundException {
        ClassLoader classLoader = bean.getClassLoader();
        assertNotNull(classLoader);
        Class clazz = classLoader.loadClass("net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean");
        assertEquals(BeanLifeCycleTestBean.class, clazz);
    }

신고
top


BeanNameAware 테스트

Spring/Chapter 3 : 2007.05.09 01:45


public class BeanLifeCycleTestBean implements BeanNameAware{

    String beanName;

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public String getBeanName(){
        return beanName;
    }

}

위와 같이 BeanNameAware 클레스를 구현해 놓고 다음과 같이 간단히 Bean으로 등록합니다.

<bean id="test" class="net.agilejava.jedi.spring.beanLifeCycle.BeanLifeCycleTestBean" />

테스트 코드를 다음과 같이 작성하고 돌려보면...

public class BeanLifeCycleTest {

    private ApplicationContext context;

    @Test
    public void testBeanNameAware() {
        context = new ClassPathXmlApplicationContext("net/agilejava/jedi/spring/beanLifeCycle/applicationContext.xml");
        BeanLifeCycleTestBean bean = (BeanLifeCycleTestBean) context.getBean("test");
        assertEquals("test", bean.getBeanName());
    }

}

녹색 막대를 확인할 수 있습니다.

이 인터페이스를 구현한 Spring의 소스 코드로는 다음과 같은 것들이 있습니다.
- ServletForwardingController
- AbstractView :: Set the view's name. Helpful for traceability.
- PortletWrappingController
- GenericFilterBean :: Stores the bean name as defined in the Spring bean factory. Only relevant in case of initialization as bean, to have a name as fallback to the filter name usually provided by a FilterConfig instance.
- JobDetailBean
- OsgiServiceProxyFactoryBean :: To find a bean published as a service by the OsgiServiceExporter, simply set this property. You may specify additional filtering criteria if needed (using the filter property) but this is not required.
- AbstractTest
- EhCacheFactoryBean
- FieldRetrievingFactoryBean :: The bean name of this FieldRetrievingFactoryBean will be interpreted as "staticField" pattern, if neither "targetClass" nor "targetObject" nor "targetField" have been specified. This allows for concise bean definitions with just an id/name.

각각의 소스코드 위에 붙어있던 JavaDoc을 보면 설정 파일에서 사용하는 bean 이름을 알면 유용한 경우가 있는 듯 합니다.
- Bean을 추적하거나 찾을 때 사용
- 특정 Bean 이름으로 필터링 할 때 사용합니다.
Interface to be implemented by beans that want to be aware of their bean name in a bean factory. Note that it is not usually recommended that an object depend on its bean name, as this represents a potentially brittle dependence on external configuration, as well as a possibly unnecessary dependence on a Spring API.
Spring API에서 인용한 부분을 보면 빈 설정의 빈 이름에 빈이 종속 되도록 하는 것을 권장하지 않습니다. 이유는 빈이 외부의 설정 파일에 종속되게 되며 이것은 Spring API에 종속되는 거나 마찬가지기 때문이라고 합니다.

신고
top


3.4.3. The other scopes

Spring/Chapter 3 : 2007.04.29 00:44


2.0에 새로 추가 된 Bean의 Scope들로 request, session, global session이 있습니다. 그리고 이 Scope들은 웹에서 사용하도록 만들어진 것이기 때문에 web-based applicationContext에서만 사용할 수 있습니다. 안그러면 IllegalStateException 이게 발생합니다.

web-based applicationContext 란?
WebApplicationContext 인터페이스를 구현한 클래스들로 다음과 같습니다.
AbstractRefreshablePortletApplicationContext, AbstractRefreshableWebApplicationContext, GenericWebApplicationContext, StaticPortletApplicationContext, StaticWebApplicationContext, XmlPortletApplicationContext, XmlWebApplicationContext
물론 위에서 abstract와 generic(여러 확장 포인트를 제공하기 위해 만든 클래스들)과 static(테스트 용도로 만들어둔 클래스들)을 제외 하면 사실상 XmlPortletApplicationContext, XmlWebApplicationContext 이 두 개가 남습니다.

3.4.3.1. Initial web configuration

새로 추가된 웹 어플리케이션을 위한 scope들을 사용하려면 web.xml에 리스너 or 필터를 등록해야 합니다.

Sevlet 2.4 이상의 버젼을 사용할 때는 아래 처럼 리스너를 등록합니다.
<web-app>
  ...
  <listener>
   <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>
  ...
</web-app>

Servlet 2.4 미만의 버젼을 사용할 때는 아래 처럼 필터를 등록합니다.
<web-app>
  ..
  <filter>
    <filter-name>requestContextFilter</filter-name>
    <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>requestContextFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  ...
</web-app>

3.4.3.2. The request scope

<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>

매 요청 마다 해당 객체를 사용할 수 있으며 각각의 요청은 서로 다른 객체를 가지게 됩니다. 그리고 요청에 대한 처리가 끝나면(컨트롤러에서 해당 메소드가 종료 되면) 더 이상 사용할 수 없습니다.

3.4.3.3. The session scope

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

매 세션 마다 해당 객체를 사용할 수 있으며 각각의 세션은 서로 다른 객체를 가지게 됩니다. 그리고 세션이 닫히면(브라우저를 끄거나 타임오버가 되면) 더 이상 사용할 수 없습니다.

3.4.3.4. The global session scope

<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>

위에서 설명한 session Scope과 동일하며 단지 포틀릿 어플리케이션에서만 사용할 수 있다는 차이가 있습니다. 포틀릿 어플리케이션이 뭔지 모르기 때문에 pass..

3.4.3.5. Scoped beans as dependencies

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

    <!-- a HTTP Session-scoped bean exposed as a proxy -->
    <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
         
          <!-- this next element effects the proxying of the surrounding bean -->
          <aop:scoped-proxy/>
    </bean>
   
    <!-- a singleton-scoped bean injected with a proxy to the above bean -->
    <bean id="userService" class="com.foo.SimpleUserService">
   
        <!-- a reference to the proxied 'userPreferences' bean -->
        <property name="userPreferences" ref="userPreferences"/>

    </bean>
</beans>

위와 같이 <aop:scoped-proxy/>를 항상 request, session, globalsession 빈을 만들 때 넣어줘야 합니다.

왜?
보통은 아래 처럼 DI하는 것을 생각할 수 있습니다.
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

하지만 이때 userPreferences 빈은 scope이 session이지만 userManager의 scope이 singletone(default가 singleton이죠.)이기 때문에 문제가 발생합니다. 매 세션 마다 새로운 객체를 만들어 줘야 하지만 저 세션 객체를 사용하는 빈의 생성을 한 번 밖에 안하기 때문에 원하던 대로 동작하지 못합니다.
따라서 매 세션 마다 새로운 객체를 만들어서 줄 프록시를 만들기 위해서 <aop:scoped-proxy/>를 사용합니다.

3.4.3.5.1. Choosing the type of proxy created

<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session">
    <aop:scoped-proxy proxy-target-class="false"/>
</bean>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

Spring AOP는 프록시 기반이며 프록시를 만들 때 인터페이스를 기반으로 만들 거라면 JDK의 API를 사용하고 클래스 기반으로 만들 때에는 CGLib을 사용합니다.

위에서도 Spring AOP를 사용하고 있고 기본적으로 CGLib을 사용하여 프록시를 만들도록 설정되어 있습니다.

대상이 되는 객체가 어떤 인터페이스를 기반으로 만들어 졌고 JDK의 프록시 API를 사용하고 싶다면 위의 예제 코드 처럼 proxy-target-class 속성의 값에 false 를 넣어 주면 됩니다.
신고

'Spring > Chapter 3' 카테고리의 다른 글

머리 뽀개지는 BeanPostProcessor  (0) 2007.05.09
Bean Life Cycle 통째로 테스트  (0) 2007.05.09
BeanFactoryAware 테스트  (0) 2007.05.09
BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
3.4.3. The other scopes  (6) 2007.04.29
Circular dependencies  (0) 2007.03.24
연습 문제 풀다가 모르는 것 체크  (0) 2007.03.24
Java Black Belt :: Spring Basic 시험 결과  (0) 2007.03.24
setParentBeanFactory 사용하기  (0) 2007.03.23
ApplicationEvent 사용 예  (2) 2007.03.16
top


Circular dependencies

Spring/Chapter 3 : 2007.03.24 23:54


참조 : Spring Reference 3.3.1.2의 오른쪽 회색 박스

Circular dependencies[각주:1]는 간단하게 교착상태에 비유할 수 있을 것 같습니다.

Constructor Injection을 사용할 때 발생할 수 있는 문제로 예를 들어 A라는 클래스의 인자로 B 클래스 타입의 객체가 필요하고 B 객체를 만들 때 생성자의 인자로 A 타입의 객체가 필요하다면... 대체.. 어떻게 A와 B를 만들 수 있을까요??[footnote]저런 생성자들만 존재한다는 전제 조건이죠.[/footenote]

이런 경우 BeanCurrentlyInCreationException 이 발생한다고 합니다.

해결책은..Setter Injection을 사용하는거죠. 아니면 다른 객체를 인자로 받아들이는 생성자 말고 다른 생성자를 사용해서 생성하는 방법도 있지만 어차피 속성을 세팅하려면 Setter Injection을 써야겠습니다.

코드로 확인해보죠.

<bean id="employee" class="circularReference.Employee">
    <constructor-arg ref="project" />
</bean>

<bean id="project" class="circularReference.Project">
    <constructor-arg ref="employee"/>
</bean>

@Test public void name(){
        ApplicationContext context =
            new ClassPathXmlApplicationContext("circularReference/circuralContext.xml");
        assertNotNull(context.getBean("project"));
    }

BeanCurrentlyInCreationException의 상위 타입인 BeanCreationException으로 나옵니다. 에러 메시지를 좀 더 읽다보면 보입니다.
사용자 삽입 이미지

아래는 에러 메시지의 Trace입니다.

more..


  1. 이전 글에서 모르겠다고 했던 circular reference를 다르게 IoC챕터 답게 표현한듯... [본문으로]
신고

'Spring > Chapter 3' 카테고리의 다른 글

Bean Life Cycle 통째로 테스트  (0) 2007.05.09
BeanFactoryAware 테스트  (0) 2007.05.09
BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
3.4.3. The other scopes  (6) 2007.04.29
Circular dependencies  (0) 2007.03.24
연습 문제 풀다가 모르는 것 체크  (0) 2007.03.24
Java Black Belt :: Spring Basic 시험 결과  (0) 2007.03.24
setParentBeanFactory 사용하기  (0) 2007.03.23
ApplicationEvent 사용 예  (2) 2007.03.16
MessageSource 사용 예  (0) 2007.03.15
top


연습 문제 풀다가 모르는 것 체크

Spring/Chapter 3 : 2007.03.24 13:55


It is a good idea to use constructor injection instead of setter injection to evade circular reference. = FALSE
=> evade circular reference. 이게 뭐지..
Circular dependencies

The prototype-scoped beans ignore lazy-init  attribute of bean  element of the wiring configuration file only if the bean is instantiated using plain BeanFactory , not using the ApplicationContext = TRUE
=> 난 false 떙!! 흠... 이 건 알아야 하는데.. 뭐더라..
=> 레퍼런스에서는 ApplicationContext에서 Singletone 빈의 상황에서 설명을 하고 있습니다. 그런데 Prototype 빈의 경우에 BeanFactory에서는 lazy-init이 무시 되나 봅니다. 왜??...

The method used as init-method  cannot be the private one. = TRUE
=> 오.. 모르겠는데;; 답은 private 이여도 되네요..하지만 public으로 해야 Spring IDE에서 읽을 수 있다는 군요.

Enter the name of the attribute of the <ref/> element (spring-beans.dtd) which DOES NOT make XML parser to validate whether Spring bean referenced by such <ref/> element exists in the wiring configuration file. = bean
=> 이건 뭐야;;  답은 bean.. 레퍼런스 3.3.3.2인가.. 3.3.2인가. <ref bean="이름" /> 이렇게 예제가 나와있었네요.
신고

'Spring > Chapter 3' 카테고리의 다른 글

BeanFactoryAware 테스트  (0) 2007.05.09
BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
3.4.3. The other scopes  (6) 2007.04.29
Circular dependencies  (0) 2007.03.24
연습 문제 풀다가 모르는 것 체크  (0) 2007.03.24
Java Black Belt :: Spring Basic 시험 결과  (0) 2007.03.24
setParentBeanFactory 사용하기  (0) 2007.03.23
ApplicationEvent 사용 예  (2) 2007.03.16
MessageSource 사용 예  (0) 2007.03.15
MessageSource 인터페이스  (2) 2007.03.15
top


Java Black Belt :: Spring Basic 시험 결과

Spring/Chapter 3 : 2007.03.24 13:48


사용자 삽입 이미지

틀린 문제 정리..

사용자 삽입 이미지
constructor 인자 구별하는 문제였는데 틀렸네요.ㅠ.ㅠ

사용자 삽입 이미지
흠.. 그럼 싱글톤인 빈은 불려지려나..

사용자 삽입 이미지
이런 실수를.. 말장난에 속아버리다니..

사용자 삽입 이미지
흠냐.. 이벤트와 ApplicationCotext 관련 문젠데...틀렸네요.


신고

'Spring > Chapter 3' 카테고리의 다른 글

BeanClassLoaderAware 테스트  (0) 2007.05.09
BeanNameAware 테스트  (0) 2007.05.09
3.4.3. The other scopes  (6) 2007.04.29
Circular dependencies  (0) 2007.03.24
연습 문제 풀다가 모르는 것 체크  (0) 2007.03.24
Java Black Belt :: Spring Basic 시험 결과  (0) 2007.03.24
setParentBeanFactory 사용하기  (0) 2007.03.23
ApplicationEvent 사용 예  (2) 2007.03.16
MessageSource 사용 예  (0) 2007.03.15
MessageSource 인터페이스  (2) 2007.03.15
3.8. The ApplicationContext  (0) 2007.03.14
top


4. Resources

Spring/Chapter 4 : 2007.03.19 12:13


참조 : http://static.springframework.org/spring/docs/2.0.x/reference/resources.html

4.1. Introduction

java.util.URL 클래스와 URL의 prefix를 다루는 표준 핸들러들로는 부족하다.
참조하는 파일이 존재 하는지 체크하는 등의 메소드가 없다.

4.2. The Resource interface

Spring의 Resource 인터페이스는 그 보다 좀 더 풍부한 기능을 제공 하도록 설계 됐다.

Resource 인터페이스와 클래스들

4.3. Built-in Resource implementations

그fjs Resource 인터페이스를 구현해 둔 클래스들이 다양하게 있다.

4.4. The ResourceLoader

ResourceLoader는 Resource 타입을 반환 해주는 인터페이스 입니다.

ResourceLoader 인터페이스
Resource, ResourceLoader 인터페이스 사용 예

4.5. The ResourceLoaderAware interface

The ResourceLoaderAware interface is a special marker interface, identifying objects that expect to be provided with a ResourceLoader reference.

ResouceLoaderAware 인터페이스

4.6. Resources as dependencies

리소스를 동적으로 바꿀 수 있게 하려면 ResourceLoader 인터페이스를 구현하게 하고 속성을 xml에서 설정하면 됩니다.

Resource를 속성으로 가지는 클래스

4.7. Application contexts and Resource paths

ApplicationContext의 생성자에 리소스의 경로를 넣어 줄 수 있습니다.
신고
top


MessageSource 사용 예

Spring/Chapter 3 : 2007.03.15 21:47


ApplicationContext가 MessageSource 인터페이스를 구현했기 때문에 ApplicationContext를 MessageSource 처럼 사용할 수 있습니다.

greeting에 관한 메시지를 받아 오는 예제를 작성해 보겠습니다.

    @Test public void messageSource(){
        MessageSource messageSouce = bf;
        assertTrue(messageSouce.getMessage("greeting", null, "Default", null).
                equals("It's good to see you"));
    }

테스트는 실패 합니다. 이 테스트를 통과 시키기 위해서는 properties 파일[각주:1]과 간단한 xml 설정이 필요합니다.

먼저 format.properties 파일을 만듭니다.
greeting=It's good to see you

xml에는 다음 과 같이 format.properties 파일을 읽을 수 있도록 설정합니다.
    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
              <list>
                <value>format</value>
              </list>
        </property>
      </bean>

그럼 이제 테스트가 통과 하는 걸 확인 할 수 있습니다. bean의 이름은 항상 messageSource여야 합니다.

이번에는 똑같이 greeting에 관한 메시지를 받아 오지만 Locale을 이용해서 Locale.KOREA와 Locale.ENGLISH를 사용하여 i18n을 해봅니다.

테스트 코드를 다음과 같이 수정합니다.
    @Test public void messageSource(){
        MessageSource messageSouce = bf;
        assertEquals(messageSouce.getMessage("greeting", null, "Default", Locale.ENGLISH)
                ,"It's good to see you");
        assertEquals(messageSouce.getMessage("greeting", null, "Default", Locale.KOREA)
                ,"hi");
    }

properties 파일 이름을 변경하고 하나를 추가합니다.
#format_en.properties
greeting=It's good to see you
#format_ko_KR.properties
greeting=hi

xml 파일은 그대로 두고 테스트를 실행합니다. 테스트는 녹색불이 켜집니다.

format 뒤에 접미어는 Locale 클래스의 상수를 보고 거기에 따라 붙여 줘야 합니다. 그래야 ResouceBundle이 Locale에 따라 적당한 properties파일로 부터 message를 읽어옵니다.

Properties 참조 : http://blog.naver.com/swucs?Redirect=Log&logNo=40007033984
  1. 하나의 번들이라고도 할 수 있겠습니다. [본문으로]
신고
top


MessageSource 인터페이스

Spring/Chapter 3 : 2007.03.15 08:55


Strategy interface for resolving messages, with support for the parameterization and internationalization of such messages.
MessageSource 인터페이스에 있는 메소드들은 다음과 같습니다.

사용자 삽입 이미지

이 인터페이스를 구현한 클래스들은 다음과 같습니다.
AbstractApplicationContext, AbstractMessageSource, AbstractRefreshableApplicationContext, AbstractRefreshablePortletApplicationContext, AbstractRefreshableWebApplicationContext, AbstractXmlApplicationContext, ClassPathXmlApplicationContext, DelegatingMessageSource, FileSystemXmlApplicationContext, GenericApplicationContext, GenericWebApplicationContext, ReloadableResourceBundleMessageSource, ResourceBundleMessageSource, StaticApplicationContext, StaticMessageSource, StaticPortletApplicationContext, StaticWebApplicationContext, XmlPortletApplicationContext, XmlWebApplicationContext
이 중에서 Reference와 MessageSource 인터페이스 API에서 언급하고 있는 클래스는 세개 입니다.

1. ResourceBundleMessageSource 클래스
JDK의 ResourceBundle 클래스MessageFormat 클래스를 기반으로 만들었으며, 번들들에 특정 이름으로 접근할 수 있는 클래스입니다.

2. ReloadableResourceBundleMessageSource 클래스
JVM 실행 도중 번들들을 다시 읽어 들이는 것이 가능합니다.

3. StaticMessageSource 클래스
MessageSource의 간단한 구현체로 기본적인 국제화를 지원하며 테스트를 위해 만들었습니다.

신고
top


3.8. The ApplicationContext

Spring/Chapter 3 : 2007.03.14 16:27


사용자 삽입 이미지

3.8.1. Internationalization using MessageSources

MessageSource 인터페이스
를 상속하고 있기 때문에 다음의 메소드들을 사용하여 Message를 받아 올 수 있습니다.

ApplicationContext가 로딩 될 때 context에 정의되어 있는 MessageSource를 자동으로 읽어 들입니다. 이때 bean의 이름은 messageSource 여야 합니다.

MessageSource 인터페이스 (2)
MessageSource 사용 예

3.8.2. Events

ApplicationEvent 클래스ApplicationListener 인터페이스를 사용해서 ApplicationContext에서 이벤트 처리를 지원합니다.

ApplicationEvent 사용 예

3.8.3. Convenient access to low-level resources

4장 Resources에서 자세히 다룰 예정이오니 pass.

3.8.4. Convenient ApplicationContext instantiation for web applications

ContextLoader를 사용해서 웹 어플리케이션에서 ApplicationContext를 선언적으로 생성할 수 있다.

일반적으로 ContexLoader를 구현한 ContextLoaderListenerContextLoaderServlet를 다음과 같이 사용합니다. Servlet 2.2 나 2.3 에서는 ContextLoderServlet을 사용해야 합니다.

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- or use the ContextLoaderServlet instead of the above listener
<servlet>
  <servlet-name>context</servlet-name>
  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
-->

신고
top


BeanFactoryPostProcessor 사용 예

Spring/Chapter 3 : 2007.03.13 16:20


BeanFactoryPostProcessor 인터페이스에는 메소드가 하나 있습니다.

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

이 인터페이스를 구현한 클래스들 입니다.
CustomEditorConfigurer, CustomScopeConfigurer, PreferencesPlaceholderConfigurer, PropertyOverrideConfigurer, PropertyPlaceholderConfigurer, PropertyResourceConfigurer, ServletContextPropertyPlaceholderConfigurer
언제 사용 하면 좋을지는.. 공부를 더 해봐야겠네요.

일단은 Java Developement with Spring 책에 있는 예제[각주:1]를 사용해 보겠습니다.
public class KeesunFactoryPostProcessor implements BeanFactoryPostProcessor {

    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        System.out.println("The factory contains the followig beans:");
        String[] beanNames = factory.getBeanDefinitionNames();
        for (int i = 0; i < beanNames.length; ++i)
            System.out.println(beanNames[i]);
    }
   
}

설정 파일에 간단하게 bean을 등록 했습니다.[각주:2]
<bean class="beanConfiguration.KeesunFactoryPostProcessor" />

그리고 여태까지 모아둔 테스트 들을 그냥 실행해 봤습니다.[각주:3]

The factory contains the followig beans:
member
혜인
keesun
keesun2
keesun3
keesun4
email
keesun5
email2
keesun6
keesun7
email3
keesun8
keesun9
keesun10
keesun11
keesun12
ticket
keesun13
keesun14
keesun15
beanConfiguration.KeesunPostProcessor
beanConfiguration.KeesunFactoryPostProcessor
콘솔창에 여태까지 Spring Reference 3장에 관한 예제를 만들면서 사용한 bean들의 name이 쭉 찍힌 것을 확인할 수 있습니다.

  1. bean factory가 가지고 있는 모든 bean을 출력하는 BeanFactoryPostProcessor [본문으로]
  2. AppicationContext 를 사용하고 있기 때문에 이렇게만 하면 됩니다. BeanFactory를 사용할 때는 아래 처럼 소스 코드에서 등록을 해줘야 합니다.<br />XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("ch03/sample8/beans.xml"));<br />AllBeansLister lister = new AllBeansLister();<br />lister.postProcessBeanFactory(factory); [본문으로]
  3. 이번에는 따로 test 메소드를 만들지 않고 그냥 콘솔 창에서 테스트 합니다. [본문으로]
신고
top


BeanPostProcessor 사용 예

Spring/Chapter 3 : 2007.03.13 15:35


BeanPostProcessor 인터페이스는 다음과 같습니다.
사용자 삽입 이미지
이 인터페이스를 구현한 클래스들 입니다. 유용하니까 만들어 뒀을 텐데 언제 어떤걸 사용하면 좋을지는 나~~~중에 알아봐야겠네요.
AbstractAdvisorAutoProxyCreator, AbstractAutoProxyCreator, ActionServletAwareProcessor, AdvisorAdapterRegistrationManager, AnnotationAwareAspectJAutoProxyCreator, ApplicationContextAwareProcessor, AspectJAwareAdvisorAutoProxyCreator, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator, InstantiationAwareBeanPostProcessorAdapter, PersistenceAnnotationBeanPostProcessor, PersistenceExceptionTranslationPostProcessor, PortletContextAwareProcessor, RequiredAnnotationBeanPostProcessor, ScriptFactoryPostProcessor, ServletContextAwareProcessor, SimplePortletPostProcessor, SimpleServletPostProcessor
SIA(Spring In Action) 74쪽 부터 몇 장에 걸쳐 postProcessAfterInitialization 메소드를 사용하는 예제가 나와있습니다.

Reference에서는 이 인터페이스를 사용하는 예제라기 보다는 BeanFactory와 Applcation Context에 등록하는 방법을 주로 다루고 있습니다.

Member 객체의 id 속성 값이 "혜인이"이라면 "이쁘니"로 값을 바꾸는 예제를 만들어 보겠습니다.
    @Test public void beanPostProcessing(){
        Member keesun15 = getMember("keesun15");
        assertTrue(keesun15.getId().equals("이쁘니"));
    }

설정 내역은 다음과 같습니다.
    <bean id="keesun15" class="beanConfiguration.Member" >
        <property name="id" value="혜인이">
    </bean>
테스트는 실패합니다. keesun15 bean의 id 속성 값이 "혜인이"이기 때문입니다.

KeesunPostProcessor 를 구현합니다.

more..

그리고 설정 파일에 bean으로 등록 해주면 테스트가 통과 합니다.[각주:1]

<bean class="beanConfiguration.KeesunPostProcessor" />

현재 사용중인 container가 ApplicationContext 종류이기 때문에 간단하게 bean으로 등록 해두기만 하면 container가 알아서 BeanPostProcessor를 읽어서 적용시켜 줍니다.

BeanFactory를 사용할 경우에는 Reference에 나온대로 addBeanPostProcessor를 소스 코드에서 등록해 줘야 합니다.
ConfigurableBeanFactory factory = new XmlBeanFactory(...);
           
    // now register any needed BeanPostProcessor instances
    MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
    factory.addBeanPostProcessor(postProcessor);

    // now start using the factory


  1. 이 객체를 받아와서 사용할 일은 없어 보이니까..id나 name을 굳이 적어줄 필요가 없겠네요. [본문으로]
신고

'Spring > Chapter 3' 카테고리의 다른 글

MessageSource 사용 예  (0) 2007.03.15
MessageSource 인터페이스  (2) 2007.03.15
3.8. The ApplicationContext  (0) 2007.03.14
'만들 수 없는 것'을 FactoryBean으로 만들기  (2) 2007.03.14
BeanFactoryPostProcessor 사용 예  (0) 2007.03.13
BeanPostProcessor 사용 예  (0) 2007.03.13
3.7. Container extension points  (0) 2007.03.13
3.6. Bean definition inheritance  (0) 2007.03.12
ObjectFactoryCreatingFactoryBean 사용 예  (0) 2007.03.12
BeanFactoryAware 사용 예  (1) 2007.03.12
BeanFactoryAware  (0) 2007.03.12
top


3.7. Container extension points

Spring/Chapter 3 : 2007.03.13 14:39


3.7.1. Customizing beans using BeanPostProcessors

Bean의 LifeCycle을 보면 initailization을 하기 전 과 후에 어떤 작업을 추가할 수 있는 인터페이스로 보입니다.

사용자 삽입 이미지

BeanPostProcessor 사용 예

3.7.2. Customizing configuration metadata with BeanFactoryPostProcessors

BeanPostProcessor와 비슷하지만 적용되는 대상이 Configuration Metadata 입니다. bean을 만들고 DI하기 전에 설정 내용을 변경할 수 있습니다.

BeanFactoryPostProcessor 사용 예

3.7.3. Customizing instantiation logic using FactoryBeans

FactoryBean 인터페이스를 구현해서 직접 factory를 만들어서 container에 끼워넣을 수 있습니다.

getBean()의 인자로 &를 붙여 주면 해당 bean 객체를 생성하는 FactoryBean을 얻을 수 있습니다.

ObjectFactoryCreatingFactoryBean 사용 예
'만들 수 없는 것'을 FactoryBean으로 만들기 (2)
신고

'Spring > Chapter 3' 카테고리의 다른 글

MessageSource 인터페이스  (2) 2007.03.15
3.8. The ApplicationContext  (0) 2007.03.14
'만들 수 없는 것'을 FactoryBean으로 만들기  (2) 2007.03.14
BeanFactoryPostProcessor 사용 예  (0) 2007.03.13
BeanPostProcessor 사용 예  (0) 2007.03.13
3.7. Container extension points  (0) 2007.03.13
3.6. Bean definition inheritance  (0) 2007.03.12
ObjectFactoryCreatingFactoryBean 사용 예  (0) 2007.03.12
BeanFactoryAware 사용 예  (1) 2007.03.12
BeanFactoryAware  (0) 2007.03.12
init-method & destroy-method  (0) 2007.03.10
top


init-method & destroy-method

Spring/Chapter 3 : 2007.03.10 14:31


사용자 삽입 이미지
이 전 글에서 사용한 방식으로 Bean의 LifeCycle에 끼어들 수도 있지만 InitializingBean이나 DisposableBean과 같은 Spring 프레임웤 소스에 종속성이 생기게 됩니다.

<bean /> 태그의 init-method 와 destroy-method 속성을 이용하여 initializingBean과 DisposableBean을 대체 할 수 있습니다.
1. 초기화 메소드와 소멸자 메소드 이름을 마음대로 정할 수 있습니다.
2. Spring 프레임웤 종속성이 생기지 않습니다.
3. 모든 bean들 에게 공통의 이름을 사용하고 싶다면 <beans /> 태그에서 default-init-method와 default-destroy-method 속성을 사용하면 됩니다.
4. <beans /> 태그에 있는 defaut-xxx-mehot 속성을 <bean /> 태그에 있는 xxx-method 가 oveeriding 합니다.

<bean id="keesun11" class="beanConfiguration.Member" init-method="init" destroy-method="dispose" />

신고

'Spring > Chapter 3' 카테고리의 다른 글

3.7. Container extension points  (0) 2007.03.13
3.6. Bean definition inheritance  (0) 2007.03.12
ObjectFactoryCreatingFactoryBean 사용 예  (0) 2007.03.12
BeanFactoryAware 사용 예  (1) 2007.03.12
BeanFactoryAware  (0) 2007.03.12
init-method & destroy-method  (0) 2007.03.10
InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
top


The IoC container

Spring/Chapter 3 : 2007.03.10 11:51


3.1. Introduction
이번 장에서는 Spring 프레임웤이 구현한 IoC에 관해 다룹니다. IoC는 Spring이 제공하는 여러 기능들에 가장 기본이 됩니다.

IoC 컨테이너의 기능은 BeanFactory와 ApplicationContext 인터페이스를 통해 제공되며 BeanFactory가 객체를 관리하기 위한 기본적인 기능을 제공하는 반면 ApplicationContext는 거기에 추가해서 보다 다양한 기능을 제공합니다.

BeanFactory와 ApplicationContext 인터페이스 비교

3.2. Basics - containers and beans
bean은 IoC container에 의해 관리 되는 객체를 말합니다. 이 둘에 대한 기본적인 내용들을 담고 있습니다.

http://whiteship.tistory.com/519

3.3. Dependencies
bean들 간의 종속성을 주입하는 방법에 대해 나와있습니다.
3.3. Dependencies

3.4. Bean scopes

종속성 뿐만 아니라 bean의 scope도 설정할 수 있습니다.
3.4. Bean scopes

3.5. Customizing the nature of a bean
bean 생명주기에 껴들어서 좀 더 bean의 설정을 취미에 맞게 바꿀수 있습니다.
3.5. Customizing the nature of a bean

3.6. Bean definition inheritance
bean 설정 파일간에 상속을 통해 bean 설정을 재사용할 수 있습니다.
3.6. Bean definition inheritance

3.7. Container extension points
Spring 프레임웤의 IoC 컴포넌트는 확장을 고려하여 설계했습니다.

3.7. Container extension points

3.8. The ApplicationContext
BeanFactory의 기본 기능에 ApplicationContext가 추가한 기능들에 대한 설명이 있습니다.

3.8. The ApplicationContext

3.9. Glue code and the evil singleton

The majority of the code inside an application is best written in a DI style, where that code is served out of a Spring IoC container, has its own dependencies supplied by the container when it is created, and is completely unaware of the container.

신고

'Spring > Chapter 3' 카테고리의 다른 글

BeanFactoryAware 사용 예  (1) 2007.03.12
BeanFactoryAware  (0) 2007.03.12
init-method & destroy-method  (0) 2007.03.10
InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
top


3.5. Customizing the nature of a bean

Spring/Chapter 3 : 2007.03.10 11:49


3.5.1. Lifecycle interfaces

Spring container에서 사용된는 bean의 lifecycle에 부가적인 일을 추가할 수 있습니다. InitializingBeanDisposableBean 같은 인터페이스를 구현 하면 됩니다. 하지만 그렇게 되면 코드가 Spring 프레임웤에 종속성이 생기기 때문에 다른 방법도 있습니다.

Bean's Life Cycle
InitializingBean & DisposableBean
init-method & destroy-method

3.5.2. Knowing who you are

BeanFactory를 가지는 bean을 만들 수 있습니다.
BeanFactoryAware 인터페이스를 구현하면 되지만 그렇게 되면 Spring 프레임웤에 종속이 되기 때문에 다른 방법도 있습니다.

BeanFactoryAware
신고

'Spring > Chapter 3' 카테고리의 다른 글

BeanFactoryAware  (0) 2007.03.12
init-method & destroy-method  (0) 2007.03.10
InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
top


Singleton & Prototype

Spring/Chapter 3 : 2007.03.09 15:07


<bean /> 엘리먼트의 scope 속성을 사용하여 bean의 scope을 지정해 줄 수 있습니다. default 값은 singleton입니다.
사용자 삽입 이미지

    <bean id="email2" class="beanConfiguration.Email" />

    <bean id="keesun6" class="beanConfiguration.Member">
        <property name="email" ref="email2" />
    </bean>

    <bean id="keesun7" class="beanConfiguration.Member">
        <property name="email" ref="email2" />
    </bean>

위와 같이 설정 해뒀다면 keesun6과 keesun7 이라는 Member bean은 같은 email 객체를 가지게 됩니다. 그래서 아래 처럼 원하지 않는 일이 발생할 수 있습니다.

@Test public void singletonScope(){
        Member keesun6 = getMember("keesun6");
        Member keesun7 = getMember("keesun7");
        Email email6 = keesun6.getEmail();
        Email email7 = keesun7.getEmail();
        assertEquals(email6, email7);
        String emailAddress = "hi@email.com";
        email6.setAddress(emailAddress);
        assertEquals(emailAddress, email7.getAddress());
    }

email2 bean의 scope을 prototype으로 지정해 줍니다.
사용자 삽입 이미지

    <!-- prototype -->
    <bean id="email3" class="beanConfiguration.Email" scope="prototype"/>

    <bean id="keesun8" class="beanConfiguration.Member">
        <property name="email" ref="email3" />
    </bean>

    <bean id="keesun9" class="beanConfiguration.Member">
        <property name="email" ref="email3" />
    </bean>

다음의 테스트를 통해서 email3 bean이 참조 대상 마다 생긴 것을 확인 할 수 있습니다.

    @Test public void prototypeScope(){
        Member keesun8 = getMember("keesun8");
        Member keesun9 = getMember("keesun9");
        Email email8 = keesun8.getEmail();
        Email email9 = keesun9.getEmail();
        assertNotSame(email8, email9);
    }

번외.. ref 에서 자동 완성 기능 사용 시 스크린 샷
사용자 삽입 이미지
역시.. 좋아요.
신고

'Spring > Chapter 3' 카테고리의 다른 글

init-method & destroy-method  (0) 2007.03.10
InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
top


3.4. Bean scopes

Spring/Chapter 3 : 2007.03.09 14:19


설정 파일에서 bean들을 정의하고 다른 bean들 과의 종속성을 정의 하는 것 말고도 각각 bean들의 scope을 설정해 줄 수 있습니다.

ScopeDescription

singleton

Spring Ioc 컨테이너 내에서 bean 정의 당 하나의 객체

prototype

매번 같은 Type의 새로운의 객체

request

Http request 당 하나 씩, web-aware ApplicationContext

session

Http session 당 하나 씩, web-aware ApplicationCotext

global session

Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context. Only valid in the context of a web-aware Spring ApplicationContext.


3.4.1. The singleton scope

Container 당 하나의 객체라는 의미에서 singleton 입니다.[각주:1]

3.4.2. The prototype scope

bean을 요청 할 때[각주:2] 마다 새로운 객체를 만들어 줍니다.

Singleton & Prototype

3.4.3. The other scopes

request, session, grobalSession은 web-based ApplicationContext에서 사용할 수 있습니다.[각주:3]

3.4.4. Custom scopes

새로운 Scope을 만들거나 기존의 Scope을 변경할 수 있습니다.
  1. JVM의 classloader당 하나의 객체라는 의미의 GoF의 Singleton과는 다릅니다. [본문으로]
  2. DI 되거나 getBean(String)에 의해 호출 될 때 [본문으로]
  3. <a href="http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/web/context/WebApplicationContext.html" target="_blank">WebApplicationContext </a>인터페이스를 구현한 클래스들을 말하는 것이 아닐지 생각해 봤습니다. [본문으로]
신고

'Spring > Chapter 3' 카테고리의 다른 글

InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
top


Autowiring

Spring/Chapter 3 : 2007.03.09 12:47


<bean /> 엘리먼트의 autowire 속성을 사용하여 bean들을 자동으로 묶을 수 있습니다. autowire에 지정할 수 있는 값은 다섯가지가 있습니다.

no : 기본값입니다. autowire를 사용하지 않겠다는 겁니다.
byName :  bean의 property 이름으로 다른 bean을 찾아서 연결합니다.
byType : bean의 property 타입으로 다른 bean을 찾아서 연결합니다. 같은 type의 bean이 여러개면 에러가 발생합니다.
constuctor : byType과 비슷한데 생성자에 있는 인자들의 Type으로 찾아서 연결합니다.
autodetect : constuctor 또는 byType으로 찾게 됩니다. default 생성자가 있으면 byType으로 찾는다는 군요.

명시적으로 <property /> 나 <constructor-arg /> 를 사용하여 종속성을 적어 줄 경우에는 autowiring으로 연결된 종속성을 overriding 합니다.
장점
1. configuration 파일의 크기를 줄여 줍니다.
2. 객체가 변하거나 추가 될 때 설정 파일의 많은 변경이 필요하지 않습니다.

단점
1. 너무 매직 스러움.
2. wiring 정보를 감춰져서 문서화 하는 도구에서 알아채질 못합니다.
3. type으로 wiring할 경우 애매한 상황이 조금이라도 발생하면 명시적으로 적어줘야 합니다.

Email 클래스를 추가하고 Member 당 하나의 Email 레퍼런스를 가지고 있습니다.

    <bean id="email" class="beanConfiguration.Email">
        <property name="type" value="google" />
        <property name="address" value="myemail@gmail.com" />
    </bean>

    <bean id="keesun5" class="beanConfiguration.Member" autowire="byName" />

Member 클래스에 setEmail(Email email) 메소드가 있기 때문에 email 이라는 이름의 bean을 찾아서 자동으로 엮어 줍니다.

    @Test public void autowiringByName(){
        Member keesun = (Member) bf.getBean("keesun5");
        Email email = keesun.getEmail();
        assertEquals("google", email.getType());
        assertEquals("myemail@gmail.com", email.getAddress());
    }



신고

'Spring > Chapter 3' 카테고리의 다른 글

Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
Constructor Injection 할 때 인자 구분  (0) 2007.03.08
top


Collection Merging

Spring/Chapter 3 : 2007.03.09 10:48


<list /> <set /> <map /> <props />는 parent bean - child bean의 관계에 있을 때 merge가 가능합니다. merge를 하고 싶을 때는 위 태그들의 속성 중에 merge 속성에 "true" 값을 주면 됩니다.

    <bean id="keesun3" class="beanConfiguration.Member">
        <property name="wishList">
            <list>
                <value>NDS</value>
                <value>Wii</value>
                <value>WOW</value>
            </list>
        </property>
    </bean>

    <bean id="keesun4" parent="keesun3" class="beanConfiguration.Member">
        <property name="wishList" >
            <list merge="true">
                <value>MacBook</value>
                <value>WOW</value>
            </list>
        </property>
    </bean>

keesun3 이 keesun4 의 parent bean인 상태에서 <list /> merge 속성을 true를 지정했기 때문에 아래의 테스트가 통과 합니다.

    @Test public void listMerging(){
        Member keesun = (Member) bf.getBean("keesun4");
        List<String> wishList = keesun.getWishList();
        assertEquals(5, wishList.size());
        assertEquals("NDS", wishList.get(0));
        assertEquals("Wii", wishList.get(1));
        assertEquals("WOW", wishList.get(2));
        assertEquals("MacBook", wishList.get(3));
        assertEquals("WOW", wishList.get(4));
    }

chile bean의 콜렉션에 같은 요소가 있을 경우 <list /> 와는 다르게 <set /> <map /> <props /> 는 child bean의 콜렉션이 parent bean에 있는 collection을 overriding 합니다.


신고

'Spring > Chapter 3' 카테고리의 다른 글

The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
Constructor Injection 할 때 인자 구분  (0) 2007.03.08
Setter Injection & Constructor Injection  (0) 2007.03.08
top


Collections - <list />

Spring/Chapter 3 : 2007.03.08 23:06


<list /> 엘리먼트는 Java의 List에 대응 합니다. 다음과 같이 설정할 수 있습니다.
    <bean id="keesun3" class="beanConfiguration.Member">
        <property name="wishList">
            <list>
                <value>NDS</value>
                <value>Wii</value>
                <value>WOW</value>
            </list>
        </property>
    </bean>
순서대로 NDS가 첫번째 WOW가 세번째 입니다.

    @Test public void list(){
        Member keesun = (Member) bf.getBean("keesun3");
        List<String> wishList = keesun.getWishList();
        assertEquals("NDS", wishList.get(0));
        assertEquals("Wii", wishList.get(1));
        assertEquals("WOW", wishList.get(2));
    }
위의 테스트 코드로 확인할 수 있습니다.

번외로.. Eclipse 자동 완성 기능 정말 좋네요.
사용자 삽입 이미지



신고

'Spring > Chapter 3' 카테고리의 다른 글

3.5. Customizing the nature of a bean  (0) 2007.03.10
Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
Constructor Injection 할 때 인자 구분  (0) 2007.03.08
Setter Injection & Constructor Injection  (0) 2007.03.08
3.3. Dependencies  (0) 2007.03.08
top


Inner beans

Spring/Chapter 3 : 2007.03.08 22:09


<propery /> 또는 <constructor-arg /> 의 하위 엘리먼트로 <bean /> 을 사용하면 됩니다.
<bean id="outer" class="...">
  <!-- instead of using a reference to a target bean, simply define the target bean inline -->
  <property name="target">
    <bean class="com.mycompany.Person"> <!-- this is the inner bean -->
      <property name="name" value="Fiona Apple"/>
      <property name="age" value="25"/>
    </bean>
  </property>
</bean>
inner bean의 id나 name 속성은 사용하지 않아도 됩니다.
=> 어차피 inner bean을 둘러싸고 있는 bean에서만 사용 될 것이기 때문에 굳이 식별자가 필요하지 않으며 id나 name을 적어도 container가 무시하게 됩니다.

inner bean의 scope는 항상 protorype 입니다.
=> 흠.. local 변수 처럼 생각하면 되겠죠?
신고

'Spring > Chapter 3' 카테고리의 다른 글

Singleton & Prototype  (0) 2007.03.09
3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
Constructor Injection 할 때 인자 구분  (0) 2007.03.08
Setter Injection & Constructor Injection  (0) 2007.03.08
3.3. Dependencies  (0) 2007.03.08
Bean 생성하기  (0) 2007.03.07
top


idref 엘리먼트

Spring/Chapter 3 : 2007.03.08 18:45


<property /> 와 <constructor-arg /> 에서 DI를 할 때 다른 bean을 참조 한다면 idref 를 사용할 수 있습니다.
<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean" />
    </property>
</bean>
이건 아래의 것과 같습니다.
<bean id="theTargetBean" class="..."/>

<bean id="client" class="...">
    <property name="targetName">
        <value>theTargetBean</value>
    </property>
</bean>

차이점
1. idref를 사용하면 참조하는 이름의 bean이 실제 존재하는지 배포 시에 검증하게 됩니다.
2. 참조 하는 bean이 같은 파일 안에 정의 되어 있을 때 <idref local="빈이름" />형태로 쓸 수 있는데 이렇게 쓰면 XML 파싱 할 때 XML 검증을 통해 설정에 문제가 있을 때 에러를 발견할 수 있습니다.

신고

'Spring > Chapter 3' 카테고리의 다른 글

3.4. Bean scopes  (0) 2007.03.09
Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
Constructor Injection 할 때 인자 구분  (0) 2007.03.08
Setter Injection & Constructor Injection  (0) 2007.03.08
3.3. Dependencies  (0) 2007.03.08
Bean 생성하기  (0) 2007.03.07
복잡한 Alias  (0) 2007.03.07
top


Constructor Injection 할 때 인자 구분

Spring/Chapter 3 : 2007.03.08 18:16


Setter Injection을 할 때는 property의 name이 표기가 되니까 어디로 들어가는 값인지 명확하지만 Constructor Injectoin을 할 때는 순서에 의존하게 되는데.. 좀.. 불명확 합니다.

   <bean id="keesun2" class="beanConfiguration.Member">
       <constructor-arg value="whiteship" />
       <constructor-arg value="1234" />
       <constructor-arg value="26" />
   </bean>

그래서 <constructor-arg /> 태그의 type 이나 index 속성을 사용해서 명확히 해주는게 좋겠습니다. 특히 primitive type의 경우에는 전부 <value /> 라는 하위 엘리먼트 또는 value 속성으로 적어 주게 되어있는데 이럴 때 써주는게 좋을 것 같습니다. non-primitive type 일 경우에는 type보다는 index가 좋겠네요. index는 0부터 시작해서 첫번째 인자를 나타냅니다.

    <bean id="keesun2" class="beanConfiguration.Member">
        <constructor-arg index="0" value="whiteship" />
        <constructor-arg index="1" value="1234" />
        <constructor-arg index="2" value="26" />
    </bean>

신고

'Spring > Chapter 3' 카테고리의 다른 글

Autowiring  (0) 2007.03.09
Collection Merging  (0) 2007.03.09
Collections - <list />  (0) 2007.03.08
Inner beans  (0) 2007.03.08
idref 엘리먼트  (0) 2007.03.08
Constructor Injection 할 때 인자 구분  (0) 2007.03.08
Setter Injection & Constructor Injection  (0) 2007.03.08
3.3. Dependencies  (0) 2007.03.08
Bean 생성하기  (0) 2007.03.07
복잡한 Alias  (0) 2007.03.07
Aliasing Beans  (0) 2007.03.07
top







티스토리 툴바