Springframework(스프링) 빈 정의 상속

2018. 7. 9. 21:55Web/Spring

스프링 빈 정의 상속


applicationContext.xml에서 2개 이상의 빈에서 같은 타입의 빈을 의존하고 있다면, 각각의 빈에서 <property> 혹은 <construct-args>로 빈을 일일이 의존할 필요가 없이 빈 정의 상속을 받을 수 있다.(사실 코드 길이가 확 줄지는 않지만 이런 방법도 있다라는 것을 보여주고 싶었다.)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.spring.study;
 
import org.apache.log4j.Logger;
 
import com.spring.study.FixedDepositDetails;
import com.spring.study.DatabaseOperations;
 
public class FixedDepositDaoImpl implements FixedDepositDao {
    private static Logger logger = Logger.getLogger(FixedDepositDaoImpl.class);
    private DatabaseOperations databaseOperations;
    
    public void setDatabaseOperations(DatabaseOperations databaseOperations) {
        this.databaseOperations = databaseOperations;
    }
    
    public FixedDepositDaoImpl() {
        logger.info("initializing");
    }
 
    public FixedDepositDetails getFixedDepositDetails(long id) {
        return databaseOperations.loadFd(id);
    }
 
    public boolean createFixedDeposit(FixedDepositDetails fdd) {
        return databaseOperations.saveFd(fdd);
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.spring.study;
 
import com.spring.study.BankStatement;
import com.spring.study.DatabaseOperations;
 
public class PersonalBankingDaoImpl implements PersonalBakingDao {
    private DatabaseOperations databaseOperations;
 
    public void setDatabaseOperations(DatabaseOperations databaseOperations) {
        this.databaseOperations = databaseOperations;
    }
 
    @Override
    public BankStatement getMiniStatement() {
        return databaseOperations.getMiniStatement();
    }
}
 
cs


이렇게 DatabaseOperations이라는 빈을 의존하는 클래스가 2개 있다고 가정해보자. 그렇다면 보통 xml 빈설정 파일에서 setter 의존 주입을 이용하여 각각의 빈정의 설정에서 DatabaseOperations 빈을 참조할 것이다.(보통 이렇게 한다. 하지만 자바에서 없어서는 안되는 상속이 있기에 여기서도 한번 이용해 보았다.)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- Root Context: defines shared resources visible to all other web components -->
    <bean id="daoTemplate" abstract="true">
        <property name="databaseOperations" ref="databaseOperations" />
    </bean>
 
    <bean id="databaseOperations"
        class="com.spring.study.DatabaseOperations" />
 
 
    <bean id="fixedDepositDao" parent="daoTemplate"
        class="com.spring.study.FixedDepositDaoImpl" />
 
 
    <bean id="personalBankingDao" parent="daoTemplate"
        class="com.spring.study.PersonalBankingDaoImpl" />    
</beans>
 
cs

이 xml 설정파일을 보면 DatabaseOperations 빈을 정의하고 daoTemplate이라는 추상화 빈정의를 하고 DatabaseOperations 빈을 참조하였다. 그리고 DatabaseOperations를 의존하는 2개의 빈에 <property>(setter빈주입) 없이 parent="daoTemplate" 속성을 추가함으로써 빈 주입이 가능하다. 여기서 추상화 빈정의를 한 빈은 인스턴스를 생성하지 않는다. 하지만 이 추상화 빈정의를 상속받는 빈정의는 반드시 구체적인 구현 클래스가 명시되어있어야한다.(이말은 추상화 빈정의에 추상화 빈정의를 상속 할 수 없다는 뜻)


부모의 빈에서 상속받는 요소들

-속성 - <property> 요소

-생성자 인자 - <constructor-arg> 요소

-메서드 재정의 

-초기화 및 소멸자 메서드

-팩터리 메서드


이런식으로 같은 빈을 여러개의 빈들이 의존하고 있다면 사용할 수 있는 방법중 한가지이다. 하지만 이렇게 빈의 정의가 적고 같은 빈의 의존하는 경우가 많지 않다면 그닥... 쓸 일이 있을지는 모르겠지만 이런 방법도 있다라는 것을 알아두면 좋을 것 같다.




빈 정의를 상속하는 여러가지 예제(부모 빈정의가 추상정의가 아닐때 포함)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
 
    <bean id="daoTemplate" abstract="true">
        <property name="databaseOperations" ref="databaseOperations" />
    </bean>
 
    <bean id="databaseOperations"
        class="sample.spring.chapter03.bankapp.utils.DatabaseOperations" />
 
    <bean id="serviceTemplate"
        class="sample.spring.chapter03.bankapp.base.ServiceTemplate">
        <property name="jmsMessageSender" ref="jmsMessageSender" />
        <property name="emailMessageSender" ref="emailMessageSender" />
        <property name="webServiceInvoker" ref="webServiceInvoker" />
    </bean>
 
    <bean id="jmsMessageSender"
        class="sample.spring.chapter03.bankapp.base.JmsMessageSender" />
    <bean id="emailMessageSender"
        class="sample.spring.chapter03.bankapp.base.EmailMessageSender" />
    <bean id="webServiceInvoker"
        class="sample.spring.chapter03.bankapp.base.WebServiceInvoker" />
 
    <bean id="controllerFactory"
        class="sample.spring.chapter03.bankapp.controller.ControllerFactory" />
 
    <bean id="controllerTemplate" factory-bean="controllerFactory"
        factory-method="getController" abstract="true">
    </bean>
 
    <bean id="fixedDepositController" parent="controllerTemplate">
        <constructor-arg index="0" value="fixedDepositController" />
        <property name="fixedDepositService" ref="fixedDepositService" />
    </bean>
 
    <bean id="fixedDepositService"
        class="sample.spring.chapter03.bankapp.service.FixedDepositServiceImpl"
        parent="serviceTemplate">
        <property name="fixedDepositDao" ref="fixedDepositDao" />
    </bean>
 
    <bean id="fixedDepositDao" parent="daoTemplate"
        class="sample.spring.chapter03.bankapp.dao.FixedDepositDaoImpl" />
 
    <bean id="fixedDepositDetails"
        class="sample.spring.chapter03.bankapp.domain.FixedDepositDetails"
        scope="prototype" />
 
    <bean id="personalBankingController" parent="controllerTemplate">
        <constructor-arg index="0" value="personalBankingController" />
        <property name="personalBankingService" ref="personalBankingService" />
    </bean>
 
    <bean id="personalBankingService"
        class="sample.spring.chapter03.bankapp.service.PersonalBankingServiceImpl"
        parent="serviceTemplate">
        <property name="personalBankingDao" ref="personalBankingDao" />
    </bean>
 
    <bean id="personalBankingDao" parent="daoTemplate"
        class="sample.spring.chapter03.bankapp.dao.PersonalBankingDaoImpl" />
 
    <bean id="userRequestController"
        class="sample.spring.chapter03.bankapp.controller.UserRequestControllerImpl">
        <property name="serviceTemplate" ref="serviceTemplate" />
    </bean>
</beans>
 
cs

여기서는 조금 다른 방법이다. 추상 빈정의가 아니라 클래스가 선언된 빈 정의도 상속 받을 수 있다. 만약 personalBankingService가 부모 빈정의인 serviceTemplate를 상속 받기 위해서는 serviceTemplate의 실제 클래스를 extends하거나 setter,construct를 serviceTemplate에 선언된 클래스에 맞게 선언 해주어야 한다.