๐ DI(Dependency Injection)
์์กด์ฑ ์ฃผ์ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋, ๊ทธ ๊ฐ์ฒด๊ฐ ์์กดํ๊ณ ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ค์ ์ธ๋ถ์์ ์ฃผ์ ํด ์ฃผ๋ ๋์์ธ ํจํด์ด๋ค.
interface MessageService {
void sendMessage(String message, String receiver);
}
class EmailService implements MessageService {
public void sendMessage(String message, String receiver) {
// ์ด๋ฉ์ผ ๋ณด๋ด๊ธฐ ๋ก์ง
}
}
์ ์ฝ๋์ ์๋ MessageService๋ฅผ MyApplication์์ ์์กดํ๊ณ ์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค.
class MyApplication {
private MessageService email = new EmailService();
public void processMessages(String message, String receiver) {
// ๋ฉ์์ง ์ฒ๋ฆฌ ๋ก์ง
email.sendEmail(message, receiver);
}
}
MyApplication ๋ด๋ถ์์ EmailService ์ธ์คํด์ค๋ฅผ ์ง์ ์์ฑํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ด๋ EmailService์ MyApplication ์ฌ์ด์ ๋์ ๊ฒฐํฉ๋๋ฅผ ์ผ๊ธฐํ๋ฉฐ, EmailService๋ฅผ ๋ค๋ฅธ ์๋น์ค๋ก ๊ต์ฒดํ๋ ค๋ฉด MyApplication์ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํด์ผ ํ๋ค.
class MyApplication {
private MessageService service;
// ์์ฑ์๋ฅผ ํตํ ์์กด์ฑ ์ฃผ์
public MyApplication(MessageService svc) {
this.service = svc;
}
public void processMessages(String message, String receiver) {
// ๋ฉ์์ง ์ฒ๋ฆฌ ๋ก์ง
service.sendMessage(message, receiver);
}
}
๊ทธ๋์ ์์ ๊ฐ์ด ์์ฑ์๋ฅผ ํตํด ์ธ๋ถ์์ ์์กด์ฑ์ ์ฃผ์ ๋ฐ์ผ๋ฉด ์ฝ๋๊ฐ ํจ์ฌ ์ ์ฐํด์ง๋ค. EmailService์ MyApplication ๊ฐ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๋ ๊ฒ๋ฟ๋ง ์๋๋ผ ํ ์คํธ์ ์ ์ง๋ณด์๊ฐ ์ฉ์ดํด์ง๋ค๋ ์ด์ ๋ํ ์ป์ ์ ์๋ค.
๐ IoC(Inversion Of Control) ์ปจํ ์ด๋
IoC๋ ์ ์ด์ ์ญ์ ์ด๋ผ๋ ๊ฐ๋ ์ผ๋ก, ๊ฐ์ฒด์ ์์ฑ ๋ฐ ๊ด๋ฆฌ ์ฑ ์์ ๊ฐ๋ฐ์๋ก๋ถํฐ ์ถ์ํ๋ ํ๋ ์์ํฌ์๊ฒ ์์ํ๋ ํ๋ก๊ทธ๋๋ฐ ์์น์ด๋ค.
์คํ๋ง ํ๋ ์์ํฌ์์๋ IoC๋ฅผ ์์กด์ฑ ์ฃผ์ ์ ํตํด ๊ตฌํํ๋ค. IoC ์ปจํ ์ด๋๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ฉฐ, ์ด ๋ฉํ๋ฐ์ดํฐ๋ XML ์ค์ ํ์ผ ํน์ ์ ํ ์ด์ (@Component)์ ํตํด ์ ๊ณต๋๋ค. ์คํ๋ง IoC ์ปจํ ์ด๋๋ ์ด ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ , ํด๋น ๊ฐ์ฒด๋ค ๊ฐ์ ์์กด์ฑ์ ์ฃผ์ ํ๋ฉฐ, ์์ฑ๋ Bean ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๋ค.
XML ๊ธฐ๋ฐ ์ค์
package learn.controller;
import learn.service.HelloService;
public class HelloController {
private HelloService helloService;
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(final HelloService helloService) {
this.helloService = helloService;
}
}
package learn.service;
public class HelloService {
}
์์ ๊ฐ์ด HelloService์ HelloController๊ฐ ์ ์๋์์ ๋, XML์ ์ด์ฉํด ์ค์ ํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ด XML ํ์ผ์ ์์ฑํด์ผ ํ๋ค.
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloController"
class="learn.controller.HelloController">
<property name="helloService" ref="service" />
</bean>
<bean id="service" class="learn.service.HelloService">
</bean>
</beans>
์์ ๊ฐ์ด <bean> ํ๊ทธ๋ฅผ ํตํด์ ์คํ๋ง ์ปจํ ์ด๋์ Bean์ ์ ์ํ๊ณ , <property> ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ์์กด์ฑ ์ฃผ์ ์ ์ค์ ํ ์ ์๋ค.
package learn;
import learn.service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import learn.controller.HelloController;
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloController helloController = context.getBean("controller", HelloController.class);
HelloService injectedHelloService = helloController.getHelloService();
System.out.println(helloController);
HelloService helloService = context.getBean("service", HelloService.class);
System.out.println(helloService.equals(injectedHelloService));
}
}
resources ํด๋ ์ ์๋ XML ํ์ผ์ ๋ถ๋ฌ์์ ApplicationContext๋ฅผ ์์ฑํ๊ณ ํ์ผ์ ์ค์ ๋ id ๊ฐ์ผ๋ก ํด๋น Bean์ ์กฐํํ๋ฉด ์ปจํ ์ด๋๊ฐ ๋ด๋ถ์ ์ผ๋ก ์์ฑํ Bean์ ์ป์ ์ ์๋ค.
์คํ ํ์๋ ์์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋๋ค. ์คํ๋ง ์ปจํ ์ด๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก Bean์ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์, ApplicationContext์์ ์ง์ ์กฐํํ HelloService ์ธ์คํด์ค์ HelloController์ ์ฃผ์ ๋ HelloService ๊ฐ์ฒด๊ฐ ์ผ์นํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
Annotation ๊ธฐ๋ฐ ์ค์
1. @Bean์ ์ด์ฉํ ์ค์
package learn.config;
import learn.service.HelloService;
import learn.controller.HelloController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public HelloService helloService() {
return new HelloService();
}
@Bean
public HelloController helloController() {
return new HelloController(helloService());
}
}
@Configuration์ ์คํ๋ง ์ค์ ์ ๋ณด(Bean ์ ์)๋ฅผ ๋ด๊ณ ์๋ ๊ฐ์ฒด์์ ๋ํ๋ด๋ ์ ํ ์ด์ ์ด๋ค. @Bean์ ๋ฉ์๋ ๋ ๋ฒจ๋ก ์ฌ์ฉ๋์ด, ํด๋น ๋ฉ์๋๊ฐ ์์ฑํ ๊ฐ์ฒด๋ฅผ ์คํ๋ง Bean์ผ๋ก ๋ฑ๋กํ๋๋ก ํ๋ ์ญํ ์ ํ๋ค. @Configuration์ด ๋ถ์ ํด๋์ค ๋ด๋ถ์ ์ ์๋ ๋ฉ์๋์ @Bean์ ์ฌ์ฉํ๋ฉด, ๊ทธ ๋ฉ์๋์ ๋ฐํ ๊ฐ์ฒด๋ ์คํ๋ง ์ปจํ ์ด๋์ ์ํด ๊ด๋ฆฌ๋๋ Bean์ผ๋ก ๋ฑ๋ก๋๋ค.
package learn;
import learn.config.AppConfig;
import learn.controller.HelloController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
HelloController helloController = context.getBean(HelloController.class);
System.out.println(helloController);
System.out.println(helloController.getHelloService());
}
}
๊ทธ๋์ AppConfig๋ฅผ ํตํด ApplicationContext๋ฅผ ๋ถ๋ฌ์ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด Bean์ด ์ ๋ฑ๋ก๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
2. @Autowired์ @Component๋ฅผ ์ด์ฉํ ์ค์
@Component
- ํด๋์ค ๋ ๋ฒจ์ ์ ๋ํ ์ด์ ์ผ๋ก ์ฌ์ฉ๋๋ฉฐ, ์ด๋ฅผ ์ฌ์ฉํ๋ฉด Spring ํ๋ ์์ํฌ๊ฐ ํด๋น ํด๋์ค๋ฅผ ์๋์ผ๋ก ์ฐพ์ Spring IoC ์ปจํ ์ด๋์์ ๊ด๋ฆฌํ๋ Bean์ผ๋ก ๋ฑ๋กํ๋ค.
- @Repository, @Service, @Controller ๋ฑ์ @Component์ ํนํ๋ ํํ๋ก, ๊ฐ๊ฐ์ ์์ญ(์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ ์ก์ธ์ค ๊ณ์ธต, ์๋น์ค ๊ณ์ธต, ํ๋ ์ ํ ์ด์ ๊ณ์ธต)์ ๋ง๊ฒ ์ถ๊ฐ์ ์ธ ํน์ง์ ์ ๊ณตํ๋ค.
@Autowired
- @Autowired๋ ํด๋์ค์ ํ๋, ์ธํฐ, ์์ฑ์์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, Spring IoC ์ปจํ ์ด๋์ ์ํด ์๋์ผ๋ก ์์กด์ฑ์ด ์ฃผ์ ๋๋ค.
- ์์ฑ์, ํ๋, ์ธํฐ ๋ฉ์๋์ ์ ์ฉํ ์ ์์ผ๋, ์์กด์ฑ ์ฃผ์ ์ ์์ด์ ์์ฑ์ ์ฃผ์ ๋ฐฉ์์ด ๊ถ์ฅ๋๋ค. ์ด๋ ์ฃผ์ ๋ฐ๋ ๊ฐ์ฒด๋ค์ ๋ถ๋ณ(immutable)์ผ๋ก ์ ์งํ ์ ์๊ฒ ํด์ฃผ๋ฉฐ, ์ํ ์์กด์ฑ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๊ณ ํ ์คํธ ์ฉ์ด์ฑ์ ๊ฐ์ ํ๋ ๋ฑ์ ์ด์ ์ด ์๋ค.
- ์์ฑ์๊ฐ ํ๋๋ง ์กด์ฌํ๊ณ , ํด๋น ์์ฑ์์ ํ๋ผ๋ฏธํฐ ํ์ ๋ค์ด Bean์ผ๋ก ๋ฑ๋ก ๊ฐ๋ฅํ ๋๋ @Autowired ์ ๋ํ ์ด์ ์ ์๋ตํ ์ ์๋ค. ์คํ๋ง์ ๊ทธ๋ฌํ ๊ฒฝ์ฐ์ ์๋์ผ๋ก ์์ฑ์๋ฅผ ํตํ ์์กด์ฑ ์ฃผ์ ์ ์๋ํ๋ค.
package learn.service;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
}
package learn.controller;
import learn.service.HelloService;
import org.springframework.stereotype.Controller;
@Controller
public class HelloController {
private HelloService helloService;
// @Autowired ์๋ต
public HelloController(HelloService helloService) {
this.helloService = helloService;
}
public HelloService getHelloService() {
return helloService;
}
}
package learn.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "learn")
public class AppConfig {
}
package learn;
import learn.config.AppConfig;
import learn.controller.HelloController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
HelloController helloController = context.getBean(HelloController.class);
System.out.println(helloController);
System.out.println(helloController.getHelloService());
}
}
์์ ๊ฐ์ด HelloController์ HelloService๋ฅผ ๊ฐ๊ฐ @Controller์ @Service ์ ๋ํ ์ด์ ์ ํตํด Bean์ผ๋ก ๋ฑ๋กํ ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฑ๋ก๋ ๋น์ ํ์ธํ ์ ์๋ค.
๐ Annotaion Based์ XML๊ณผ์ ๊ด๊ณ
Annotaion Based ์ค์
์ ๋ํ ์ด์ ๊ธฐ๋ฐ ์ค์ ์ Spring์์ ๊ฐ์ฒด์ ์์ฑ๊ณผ ์์กด์ฑ ์ฃผ์ ์ ํ์ผ ๋์ ํด๋์ค, ๋ฉ์๋, ๋๋ ํ๋ ์ ์ธ์ ์ง์ ์ฌ์ฉํ์ฌ ์ฌ๊ตฌ์ฑ์ ์ํํ๋ค.
Annotaion Based์ ์ฅ์
1. ์ฝ๋ ๋ด ๊ด๋ จ์ฑ
์ ๋ํ ์ด์ ์ ์ฌ์ฉํจ์ผ๋ก์จ, ์์กด์ฑ ๊ด๋ฆฌ์ ๊ด๋ จ๋ ์ค์ ์ ๋ณด๊ฐ ์ฝ๋ ๋ด์ ์์นํ๊ฒ ๋๋ฏ๋ก, ์ฝ๋๋ฅผ ์ฝ๋ ์ฌ๋์ ํด๋์ค์ ์ญํ ๊ณผ ์์กด์ฑ ๊ด๋ฆฌ ๋ฐฉ์์ ํ๋์ ๋ณผ ์ ์๋ค.
2. ๊ฐํธํ ์ค์
XML ๊ธฐ๋ฐ ์ค์ ์ ๋นํด ๊ฐ๊ฒฐํ๊ณ ๋ช ํํ ์ค์ ์ด ๊ฐ๋ฅํด์ง๋ค. ๋ณต์กํ ํ์ผ์ ๊ด๋ฆฌํ๋ ๋์ ํด๋์ค์ ์ง์ ์ ๋ํ ์ด์ ์ ์ ์ฉํ์ฌ ์์กด์ฑ์ ์ฃผ์ ๋ฐ์ ์ ์๋ค.
3. ์ ์ง๋ณด์์ฑ ํฅ์
์ ๋ํ ์ด์ ์ ํ์ฉํ ์ค์ ์ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ ์ ์ง๋ณด์๋ฅผ ์ฉ์ดํ๊ฒ ํ๋ค. @ComponentScan์ ํ์ฉํ๋ฉด ์ง์ ๋ ํจํค์ง์์ @Component, @Service ๋ฑ์ ์ ๋ํ ์ด์ ์ ๊ฐ๋ ํด๋์ค๋ค์ ์๋์ผ๋ก ์ค์บํ์ฌ ๋น์ ๋ฑ๋กํ ์ ์๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ๊ท๋ชจ๊ฐ ์ปค์ง๋๋ผ๋ ๊ด๋ฆฌ๊ฐ ์ฝ๋ค.
XML๊ณผ์ ๊ด๊ณ
์ ๋ํ ์ด์ ๊ธฐ๋ฐ ์ค์ ๊ณผ XML ์ค์ ์ ์ํธ ๋ณด์์ ์ผ๋ก ์ฌ์ฉ๋ ์ ์๋ค. ์ ๋ํ ์ด์ ์ด ํด๋์ค์ ์ง์ ์ ์ฉ๋์ด ๊ฐ๋ ์ฑ์ด ๋์์ง์ง๋ง, XML์ ์ฌ์ฉํ๋ฉด ํด๋์ค๋ฅผ ์์ ํ์ง ์๊ณ ๋ ์์กด์ฑ์ ์ฃผ์ ํ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ค. ์ค์ ๋ก Spring์ ์ ๋ํ ์ด์ ๊ณผ XML ์ค์ ์ ํผํฉํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฉํ๋ค. ๋จ, ์ ๋ํ ์ด์ ์ ์ด์ฉํ ์ฃผ์ ์ด XML์ ํตํ ์ฃผ์ ๋ณด๋ค ์ฐ์ ์๋๋ค. ์ ๋์ ์ผ๋ก ์ด๋ ๋ฐฉ์์ด ๋ ๋ซ๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ฆฌ๊ธฐ ์ด๋ ต๊ธฐ์ ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ ๋ฐฉ์์ ์ ํํ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค.
https://docs.spring.io/spring-framework/reference/core/beans/annotation-config.html#page-title
https://docs.spring.io/spring-framework/reference/core/beans/java/configuration-annotation.html
https://docs.spring.io/spring-framework/reference/core/beans/introduction.html
https://docs.spring.io/spring-framework/reference/core/beans/basics.html