일반적인 제어의 흐름은 각 객체에게 제어권이 있는 것으로 객체 자신이 사용할 객체를 스스로 선택하고 스스로 생성한다
프레임워크에서 제어는 프레임워크에게 있다. 단순히 불러와 사용하는 라이브러리와 달리 개발자가 작성한 어플리케이션 코드가 프레임워크에 의해 사용되기 때문. 이런 일반적인 제어의 흐름과 반대되는 것이 IoC이다
객체의 생성과 파괴, 조합, 객체간 의존 관계를 설정하는 객체
어떠한 클래스를 사용할지 등록하면, 필요한 의존 관계를 맺고 생명 주기를 관리해 인스턴스를 반환한다
IoC 컨테이너 객체를 클라이언트로 객체들은 의존성을 주입 받을 수 있어 결합도가 느슨해진다
스프링에선 ApplicationContext 인터페이스를 통해 이를 제공한다
스프링의 IoC 컨테이너
ApplicationContext에 의해 관리되는 객체들을 Bean이라고 한다
ApplicationContext은 실제 만들어야할 Bean 정보를 Configuration Metadata로부터 받아온다. 이는 자바(AnnotationConfigApplicationContext) 또는 xml(GenericXmlApplicationContext)로 작성할 수 있다
// AppConfiguration.java
@Configuration // 스프링의 애노테이션으로 ApplicationContext의 설정 메타데이터로 인식되게 한다
public class AppConfiguration {
@Bean // 아래 메소드는 Bean을 정의한 Configuration Metadata가 된다
public ExampleBean exampleBean() {
return new ExampleBean();
}
}
// 설정파일로 어플리케이션 컨택스트 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfiguration.class);
// Bean 생성
ExampleBean exBean = applicationContext.getBean(ExampleBean.class);
ClassName.class
: @Configuration
public class AppConfiguration {
@Bean
public ExampleBean exampleBean() {
return new ExampleBean();
}
@Bean
public AnotherBean antoherBean() {
return new AnotherBean(exampleBean());
}
}
@Configuration
public class AppConfiguration {
@Bean
public ExampleBean exampleBean() {
return new ExampleBean();
}
@Bean
public AnotherBean antoherBean(ExampleBean exampleBean) {
return new AnotherBean(exampleBean);
}
}
// ObjectA는 ObjectB의 인스턴스의 생성을 기다리고 ObjectB는 ObjectA의 인스턴스 생성을 기다린다
@Configuration
public class AppConfiguration {
@Bean
public ObjectA objectA(ObjectB objectB) {
return new ObjectA(objectB);
}
@Bean
public ObjectB objectB(ObjectA objectA) {
return new ObjectB(objectA);
}
}
위에서 설정 파일을 통해 ApplicationContext를 생성하고,
close()
로 소멸할 수 있다applicationContext.close();
application context가 소멸되면, 등록되어 있는 Bean들도 소멸된다
close()
로 Application Context를 소멸하지 않으면 Bean 소멸 콜백도 호출되지 않는다
콜백 함수 : 다른 코드의 인수로서 넘겨주는 실행 가능한 코드. 콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행할 수도 있고, 나중에 실행할 수도 있다
@PostConstruct
애너테이션이 적용된 메소드 호출 (있다면)InitializingBean
인터페이스 구현시 afterPropertiesSet
호출@Bean
애너테이션의 initMethod
에 설정한 메소드 호출@Component
public class SomeComponent implements InitializingBean {
// @PostConstruct 적용 메소드
@PostConstruct
public void postConstruct() {
System.out.println("postConstruct 호출");
}
// InitializingBean 구현 메소드
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet 호출");
}
}
...다른파일...
@Configuration
public class Config {
// initMethod 설정 메소드
@Bean(initMethod = "init")
public Component component() {
...
}
}
class Component {
public void init() {
...
}
}
@PreDestroy
애너테이션이 적용된 메소드 호출 (있다면)DisposableBean
인터페이스 구현시 destroy 호출@Bean
애너테이션의 destroyMethod
에 설정한 메소드 호출@Component
public class SomeComponent implements DisposableBean {
@PreDestroy
public void preDestroy() {
System.out.println("preDestroy 호출");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy 호출");
}
}
...다른파일...
@Configuration
public class Config {
// destroyMethod 설정 메소드
@Bean(destroyMethod = "destroyMethod")
public Component component() {
...
}
}
class Component {
public void destroyMethod() {
...
}
}