2023. 12. 10. 20:37ㆍSpring Framework/Spring IoC
📌 Spring Bean의 의존성(Dependencies) 및 상세 설정(Configuration) 정리
🔹 1️⃣ 의존성(Dependency) 정의 방법
Spring에서는 Bean의 속성이나 생성자 아규먼트를 설정할 때 다양한 방법으로 값을 지정할 수 있습니다.
주요 방식은 다음과 같습니다.
방식 | 설명 |
---|---|
직접 값 지정 (Primitive, String 등) | 단순한 값(문자열, 숫자, boolean 등) 설정 |
idref | 특정 Bean의 id 를 안전하게 참조하는 방법 |
ref | 다른 Bean을 참조하여 의존성 설정 |
내부 Bean (Inner Bean) | Bean 내부에서 직접 새로운 Bean을 정의 |
컬렉션 (List, Set, Map, Properties) | 컬렉션 타입 속성 설정 |
컬렉션 병합 (Merging) | 부모 Bean의 컬렉션을 자식 Bean이 상속하여 확장 가능 |
null 값 지정 | Bean 속성을 null 로 설정 |
p-namespace | XML에서 속성을 한 줄로 간결하게 표현 |
c-namespace | XML에서 생성자 주입을 한 줄로 간결하게 표현 |
중첩 속성(Compound Property) | 다단계 속성을 한 번에 설정 가능 |
🔹 2️⃣ 값(Primitive, String 등) 설정
📍 디폴트 <value>
사용
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="mypassword"/>
</bean>
package com.intheeast.ioc.dependenciesandconfigurationindetail.straightvalues.config;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
@Configuration
public class AppConfig {
@Bean
public DataSource myDataSource() throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(com.mysql.cj.jdbc.Driver.class);
dataSource.setUrl("jdbc:mysql://localhost:3306/sbdt_db");
dataSource.setUsername("root");
dataSource.setPassword("1234");
return dataSource;
}
}
➡️ 문자열, 숫자 등의 디폴트 값을 설정하는 방식
📍 p-namespace를 활용한 간결한 표현
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="mypassword"/>
➡️ 속성을 줄여 가독성을 높이는 방법, 다만 IDE에서 자동 완성 지원이 부족할 수 있음
🔹 3️⃣ idref
를 활용한 안전한 Bean 참조
✔ idref
는 다른 Bean의 id
를 문자열로 안전하게 참조하는 방법입니다.
<bean id="theTargetBean" class="com.example.MyBean"/>
<bean id="theClientBean" class="com.example.ClientBean">
<property name="targetName">
<idref bean="theTargetBean"/>
</property>
</bean>
➡️ idref
는 잘못된 ID 입력을 방지하는 역할을 하며, 런타임 오류를 줄여줍니다.
❌ 잘못된 방법 (ref
를 직접 문자열로 넣는 경우)
<property name="targetName" ref="theTargetBean"/> <!-- 런타임 시 오류 발생 가능 -->
✔ idref
를 사용하면 Spring이 theTargetBean
이 존재하는지 사전에 검증
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public TargetBean theTargetBean() {
return new TargetBean();
}
@Bean
public ClientBean theClientBean() {
ClientBean client = new ClientBean();
client.setTargetName("theTargetBean"); // 직접 ID를 설정
return client;
}
}
🔹 4️⃣ ref
를 활용한 Bean 의존성 주입
✔ ref
는 다른 Bean 객체를 직접 참조하는 방법입니다.
<bean id="serviceA" class="com.example.ServiceA"/>
<bean id="serviceB" class="com.example.ServiceB">
<property name="serviceA" ref="serviceA"/>
</bean>
➡️ serviceB
가 serviceA
를 의존하는 경우, ref="serviceA"
를 통해 주입
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
// serviceB가 serviceA를 의존하는 경우, ref="serviceA"를 통해 주입
@Bean
public ServiceA serviceA() {
return new ServiceA();
}
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
anotherBean.setDependency(serviceA()); // ref bean="serviceA"
return serviceB;
}
}
📍 부모 컨텍스트의 Bean 참조 (parent
속성 사용)
<!-- 부모 컨텍스트 -->
<bean id="accountService" class="com.example.AccountService"/>
<!-- 자식 컨텍스트 -->
<bean id="accountService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref parent="accountService"/>
</property>
</bean>
➡️ 부모 컨텍스트에 있는 Bean을 자식 컨텍스트에서 참조하는 경우 parent
속성을 사용
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext parentContext = new AnnotationConfigApplicationContext(ParentConfig.class);
AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext(ChildConfig.class);
childContext.setParent(parentContext);
AccountService accountService = childContext.getBean("accountService", AccountService.class);
// childContext에서 accountService 빈 사용
}
}
@Configuration
public class ParentConfig {
@Bean
public AccountService accountService() {
return new SimpleAccountService();
}
}
@Configuration
public class ChildConfig {
@Bean
public AccountService accountService() {
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setTarget(accountService()); // 부모 컨텍스트의 빈 참조
return (AccountService) proxyFactoryBean.getObject();
}
}
🔹 5️⃣ 내부 Bean (Inner Bean) 정의
✔ 특정 Bean에서만 사용할 익명 Bean을 생성하는 방법입니다.
<bean id="outer" class="com.example.OuterClass">
<property name="target">
<bean class="com.example.InnerClass">
<property name="name" value="John Doe"/>
<property name="age" value="30"/>
</bean>
</property>
</bean>
➡️ InnerClass
는 OuterClass
에서만 사용되며, 개별적으로 접근할 수 없음
🔹 6️⃣ 컬렉션(List, Set, Map, Properties) 설정
✔ Spring에서는 list
, set
, map
, props
를 통해 컬렉션 데이터를 설정할 수 있습니다.
<bean id="complexObject" class="com.example.ComplexObject">
<property name="adminEmails">
<props>
<prop key="admin">admin@example.com</prop>
<prop key="support">support@example.com</prop>
</props>
</property>
<property name="someList">
<list>
<value>List Element 1</value>
<ref bean="myDataSource"/>
</list>
</property>
<property name="someMap">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value-ref="myDataSource"/>
</map>
</property>
<property name="someSet">
<set>
<value>Set Element 1</value>
<ref bean="myDataSource"/>
</set>
</property>
</bean>
➡️ 컬렉션 데이터를 Spring 설정 파일에서 직접 지정 가능
🔹 7️⃣ 컬렉션 병합(Collection Merging)
✔ 부모 Bean에서 정의한 컬렉션을 자식 Bean에서 확장 가능
<bean id="parent" abstract="true" class="com.example.ComplexObject">
<property name="adminEmails">
<props>
<prop key="admin">admin@example.com</prop>
<prop key="support">support@example.com</prop>
</props>
</property>
</bean>
<bean id="child" parent="parent">
<property name="adminEmails">
<props merge="true">
<prop key="sales">sales@example.com</prop>
<prop key="support">support@otherdomain.com</prop>
</props>
</property>
</bean>
➡️ merge="true"
를 사용하면 부모의 컬렉션 데이터를 유지하면서 추가/수정 가능
public class ComplexObject {
private Properties adminEmails;
private List<Object> someList;
private Map<String, Object> someMap;
private Set<Object> someSet;
// Getters and Setters for each property
public void setAdminEmails(Properties adminEmails) {
this.adminEmails = adminEmails;
}
public void setSomeList(List<Object> someList) {
this.someList = someList;
}
public void setSomeMap(Map<String, Object> someMap) {
this.someMap = someMap;
}
public void setSomeSet(Set<Object> someSet) {
this.someSet = someSet;
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.*;
@Configuration
public class AppConfig {
@Bean
public ComplexObject moreComplexObject() {
ComplexObject complexObject = new ComplexObject();
Properties adminEmails = new Properties();
adminEmails.put("administrator", "administrator@example.org");
adminEmails.put("support", "support@example.org");
adminEmails.put("development", "development@example.org");
complexObject.setAdminEmails(adminEmails);
List<Object> someList = new ArrayList<>();
someList.add("a list element followed by a reference");
someList.add(myDataSource());
complexObject.setSomeList(someList);
Map<String, Object> someMap = new HashMap<>();
someMap.put("an entry", "just some string");
someMap.put("a ref", myDataSource());
complexObject.setSomeMap(someMap);
Set<Object> someSet = new HashSet<>();
someSet.add("just some string");
someSet.add(myDataSource());
complexObject.setSomeSet(someSet);
return complexObject;
}
@Bean
public MyDataSource myDataSource() {
return new MyDataSource();
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import java.util.Properties;
@Configuration
public class AppConfig {
@Bean
public ComplexObject parent() {
ComplexObject parent = new ComplexObject();
Properties adminEmails = new Properties();
adminEmails.put("administrator", "administrator@example.com");
adminEmails.put("support", "support@example.com");
parent.setAdminEmails(adminEmails);
return parent;
}
@Bean
public ComplexObject child() {
GenericBeanDefinition childDefinition = new GenericBeanDefinition();
childDefinition.setParentName("parent");
childDefinition.setBeanClass(ComplexObject.class);
ComplexObject child = new ComplexObject();
Properties adminEmails = new Properties();
adminEmails.put("sales", "sales@example.com");
adminEmails.put("support", "support@example.co.uk"); // overriding
child.setAdminEmails(adminEmails);
return child;
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class AppConfig {
@Bean
public SomeClass something() {
SomeClass someClass = new SomeClass();
Map<String, Float> accounts = new HashMap<>();
accounts.put("one", 9.99f);
accounts.put("two", 2.75f);
accounts.put("six", 3.99f);
someClass.setAccounts(accounts);
return someClass;
}
}
🔹 8️⃣ null
및 빈 문자열 설정
✔ 속성을 null
로 설정하려면 <null/>
태그 사용
<bean class="com.example.MyBean">
<property name="email">
<null/>
</property>
</bean>
➡️ exampleBean.setEmail(null);
과 동일한 효과
✔ 속성을 빈 문자열로 설정
<bean class="com.example.MyBean">
<property name="email" value=""/>
</bean>
➡️ exampleBean.setEmail("");
과 동일한 효과
🔹 9️⃣ p-namespace & c-namespace 단축 표현
✔ p-namespace (Setter 주입 간결화)
<bean id="john" class="com.example.Person" p:name="John Doe" p:spouse-ref="jane"/>
✔ c-namespace (생성자 주입 간결화)
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo" c:thingThree-ref="beanThree"/>
➡️ 코드를 간결하게 만들지만, IDE 자동 완성이 부족할 수 있음
🔹 🔟XML 기반 Properties 설정 방법
Spring에서는 java.util.Properties 타입을 설정할 때 XML의 <value> 요소를 활용할 수 있습니다.
<bean id="mappings"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<!-- typed as a java.util.Properties -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
✔ JavaBeans PropertyEditor 메커니즘을 활용하여 변환이 자동으로 수행됨
💡 Spring에서는 value 속성 스타일보다 value 요소를 중첩하는 방식을 선호
➡️ 가독성이 높고, 여러 개의 key-value를 쉽게 관리 가능
🔹 Java 기반 Properties 설정 방법
💡 Spring의 @Configuration을 사용하여 Properties를 설정할 수도 있습니다.
✔ Java 코드로 설정하면 더욱 직관적이며, IDE 자동 완성을 활용할 수 있습니다.
📍 Java 기반 구성 (@Configuration 사용)
package com.intheeast.ioc.dependenciesandconfigurationindetail.straightvalues.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
@Configuration
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
Properties properties = new Properties();
properties.setProperty("jdbc.driver.className", "com.mysql.cj.jdbc.Driver");
properties.setProperty("jdbc.url", "jdbc:mysql://localhost:3306/sbdt_db");
configurer.setProperties(properties);
return configurer;
}
@Value("${jdbc.driver.className}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Bean
public DataSource myDataSource() throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass((Class<? extends java.sql.Driver>) Class.forName(driverClassName));
dataSource.setUrl(url);
dataSource.setUsername("root");
dataSource.setPassword("1234");
return dataSource;
}
}
✔ PropertySourcesPlaceholderConfigurer를 사용하여 Properties 객체를 생성
✔ @Value 어노테이션을 활용하여 프로퍼티 값(jdbc.driver.className, jdbc.url)을 주입
✔ Spring의 SimpleDriverDataSource를 사용하여 DataSource 설정
✔ Class.forName(driverClassName)을 사용하여 동적으로 드라이버 클래스 로드 가능
💡 Java 기반 구성 방식의 장점
✔ IDE 자동 완성 지원 (오타 방지 및 유지보수 용이)
✔ Java 코드에서 직접 Properties를 다룰 수 있어 가독성 및 확장성 증가
✔ 테스트 시 Properties 값을 동적으로 변경 가능
🔹 Spring Bean 설정 정리 📝
✔ Bean 속성을 설정하는 다양한 방법 지원
✔ ref
, idref
, inner bean
, 컬렉션
, null 값
등의 다양한 설정 방식 제공
✔ p-namespace
, c-namespace
를 활용하여 XML을 간결하게 표현 가능
✔ 컬렉션 병합을 통해 부모 Bean 데이터를 재사용 가능
💡 Spring 설정을 활용하면 객체 간 결합도를 낮추고, 유지보수성을 높일 수 있습니다! 🚀
Dependencies and Configuration in Detail :: Spring Framework
The , , , and elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. The following example shows how to use them: [email protected] [email protected] [email protected] a list element followed
docs.spring.io
'Spring Framework > Spring IoC' 카테고리의 다른 글
Bean Overview (0) | 2024.06.11 |
---|---|
Using @Autowired (0) | 2023.12.10 |
Fine-tuning Annotation-based Autowiring with @Primary or @Fallback (0) | 2023.07.08 |
Dependency Injection of Spring Framework (0) | 2023.05.01 |
Bean Definition Inheritance (0) | 2023.04.28 |