Spring 초기셋업로직

@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");
    }
}

Categories:

Updated:

Comments