@Component
public class InvalidInitExampleBean {
@Autowired
private Environment environment;
public InvalidInitExampleBean() {
environment.getActiveProfiles();
}
}
- IoC의 특성상 단순히 Bean의 생성자에 초기화 로직을 넣기만 해서는 안될 수 있다.
- InvalidInitExampleBean 객체가 생성되는 시점에는 environment가 초기화되지 않은 상태이므로 NullPointerException이 발생한다.
@PostConstruct 어노테이션
- @PostConstruct 어노테이션은 특정 클래스의 메소드에 붙여서 해당 클래스의 객체 내 모든 의존성(Bean)들이 초기화 된 직후 딱 한번 실행됨
@Component
@Slf4j
public class PostConstructExampleBean {
@Autowired
private Environment environment;
@PostConstruct
public void init() {
log.info("@PostConstruct {}",Arrays.asList(environment.getDefaultProfiles()));
}
}
InitializingBean 인터페이스
- InitializingBean 인터페이스와 afterPropertiesSet() 메소드를 구현
@Component
@Slf4j
public class InitializingBeanExampleBean implements InitializingBean {
@Autowired
private Environment environment;
@Override
public void afterPropertiesSet() throws Exception {
log.info("{}", Arrays.asList(environment.getDefaultProfiles()));
}
}
ApplicationListener
- 앞의 방식처럼 특정 Bean과 관련된 것이 아니라 모든 Bean의 초기화가 완료된 후 실행되도록 하는 방식
- ApplicationListener 인터페이스를 구현하는 Bean 을 정의하고 onApplicationEvent() 메소드를 Override
@Component
@Slf4j
public class StartupApplicationListenerExample implements ApplicationListener<ContextRefreshedEvent> {
public static int counter;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
log.info("counter {}", counter++;);
}
}
@EventListener 어노테이션
- ApplicationListener처럼 Bean을 하나 정의하고, 인터페이스를 구현하는 것이 아니라 특정 메소드에 @EventListener 어노테이션을 붙여 그 안에 원하는 로직 작성
@Component
@Slf4j
public class EventListenerExampleBean {
public static int counter;
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
log.info("counter {}", counter++;);
}
}
@Bean의 initMethod 속성
- @Bean 어노테이션의 initMethod 속성으로 이 Bean 의 초기화가 완료(의존성이 모두 주입)된 뒤에 실행 되어야할 Bean 내 메소드의 이름을 지정
@Slf4j
public class PostConstructExampleBean {
@Autowired
private Environment environment;
@PostConstruct
public void init() {
log.info("@Bean initMethod {}",Arrays.asList(environment.getDefaultProfiles()));
}
}
@Bean(initMethod="init")
public InitMethodExampleBean exBean() {
return new InitMethodExampleBean();
}
생성자 Injection
- Field injection 의 경우 Bean 객체를 생성한 뒤에 나중에 의존성을 주입하기 때문에, 주입하기 이전에는 null 인 상태지만 Constructor Injection 의 경우에는 생성과 동시에 주입
@Component
@Slf4j
public class LogicInConstructorExampleBean {
private final Environment environment;
@Autowired
public LogicInConstructorExampleBean(Environment environment) {
this.environment = environment;
log.info("Constructor Injection {}",Arrays.asList(environment.getDefaultProfiles()));
}
}
SpringBoot의 CommandLineRunner
- SpringBoot는 run() 이라는 콜백 메소드를 가진 CommandLineRunner 라는 인터페이스를 제공
- run() 메소드는 Spring Application Context 의 초기화가 완료된(모든 Bean이 초기화된) 후에 실행되므로 이 안에 원하는 로직을 작성
- CommandLineRunner Bean 은 같은 애플리케이션 컨텍스트 내에 여러개를 정의할 수 있으며, Ordered 인터페이스, 혹은 @Order 어노테이션으로 실행 순서를 정할 수 있음
@Component
@Slf4j
public class CommandLineAppStartupRunner implements CommandLineRunner {
public static int counter;
@Override
public void run(String...args) throws Exception {
log.info("counter {}", counter++;);
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner run(UserRepository userRepository) throws Exception {
return (String[] args) -> {
User user1 = new User("John", "john@domain.com");
User user2 = new User("Julie", "julie@domain.com");
userRepository.save(user1);
userRepository.save(user2);
userRepository.findAll().forEach(user -> System.out.println(user));
};
}
}
SpringBoot의 ApplicationRunner
- 스프링 부트는 앞서 언급한 CommandLineRunner 인터페이스 외에 ApplicationRunner 인터페이스도 제공한다.
- run() 이라는 콜백 메소드를 가지고 있어 이 안에 원하는 로직을 작성
@Component
@Slf4j
public class AppStartupRunner implements ApplicationRunner {
public static int counter;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("Application started with option names : {}", args.getOptionNames());
log.info("Increment counter");
counter++;
}
}
모두 적용
@Component
@Slf4j
@Scope(value = "prototype")
public class AllStrategiesExampleBean implements InitializingBean {
public AllStrategiesExampleBean() {
log.info("Constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitializingBean");
}
@PostConstruct
public void postConstruct() {
log.info("PostConstruct");
}
public void init() {
log.info("init-method");
}
}
Comments