해당 객체가 생성된 이후, JAVA reflection 기술로 필드에 값을 주입한다.
테스트 코드상에서 편하게 사용한다.클래스 필드를 setter를 통해 주입
단점:
변경된 클래스의 주소값과 변경된 클래스의 주소값이 동일하기에, 일반적인 객체 비교를 할 수 없다.객체는 불변객체로 설정하는 것이 지향하는 바이다.클래스 필드를 생성자를 통해 주입
장점:
순환참조
: 두 객체가 서로를 의존하고 있을 때 발생해결방법
: 중간객체를 두어 두 클래스가 서로 중간객체를 필드로 갖게끔 한다.
ex. Board, Member
Board: MemberVO(중간객체), ...
Member: BoardVO(중간객체), ...
@Service
public class PokemonService {
// 설명. 필드 주입
@Autowired
@Qualifier("squirtle")
private Pokemon pokemon;
// 설명. 생성자 주입
@Autowired
public PokemonService(@Qualifier("charmander") Pokemon pokemon) {
this.pokemon = pokemon;
}
public void pokemonAttack() {
pokemon.attack();
}
}
@Service
public class PokemonService {
// 설명. Pokemon(type)으로 처리 시
@Resource(name="charmander")
private Pokemon pokemon;
@Resource(name="charmander")
private List<Pokemon> pokemonList;
public void pokemonAttack() {
pokemonList.forEach(Pokemon::attack);
}
}
@Service("pokemonServiceInject")
public class PokemonService {
// 설명. 필드 주입 가능
@Inject
@Named("squirtle")
private Pokemon pokemon;
// 설명. 생성자 주입 가능
@Inject
public PokemonService(@Named("charmander") Pokemon pokemon) {
this.pokemon = pokemon;
}
// 설명. setter 주입 가능
@Inject
public void setPokemon(@Named("pikachu")Pokemon pokemon) {
this.pokemon = pokemon;
}
public void pokemonAttack() {
pokemon.attack();
}
}
singleton: 하나의 인스턴스만을 생성하며 해당 인스턴스가 공유된다.
@Configuration
public class Configuration {
...
@Bean
@Scope("singleton") // 스프링 컨테이너(IOC Container)는 bean 객체를 기본적으로 싱글톤으로 관리한다. (생략 가능)
public Shopping cart() {
return new ShoppingCart();
}
}
prototype: 매번 bean이 필요로 할 때 새로 인스턴스를 생성한다.
@Configuration
public class Configuration {
...
@Bean
@Scope("prototype") // bean 객체의 life cycle을 다른 주기로 가져갈 수 있다
public Shopping cart() {
return new ShoppingCart();
}
}
사실 Tomcat이 사용자마다 thread를 할당하고 thread마다 객체를 필요로 하기에, 전체 사용자가 공용으로 사용하는 객체는 개념상 분리되어있다. 따라서 아래의 request, session, globalSession은 사용할 일이 거의 없다.
request:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {
// 필드 및 메서드 정의
}
session: http 세션 당 하나의 인스턴스를 새로 생성하고 세션이 종료되면 인스턴스를 파기
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionScopedBean {
// 필드 및 메서드 정의
}
globalSession: 전역 세션 당 하나의 인스턴스를 생성하고 전역 세션이 종료되면 인스턴스를 파기
@Component
@Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class GlobalSessionScopedBean {
// 필드 및 메서드 정의
}
I18N
public class Application {
public static void main(String[] args) {
// 다국어 메시지 처리
ApplicationContext context = new AnnotationConfigApplicationContext(ContextConfiguration.class);
String error404MessageKR = context.getMessage("error.404", null, Locale.KOREA);
String error500MessageKR = context.getMessage("error.500", new Object[] {"나", new Date()}, Locale.KOREA);
String error404MessageUS = context.getMessage("error.404", null, Locale.US);
String error500MessageUS = context.getMessage("error.500", new Object[] {"ME", new Date()}, Locale.US);
System.out.println("error404MessageKR: " + error404MessageKR);
System.out.println("error500MessageKR: " + error500MessageKR);
System.out.println("error404MessageUS: " + error404MessageUS);
System.out.println("error500MessageUS: " + error500MessageUS);
}
}
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
@Configuration
public class ContextConfiguration {
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
// 설명. 접속하는 세션의 로케일(Locale)에 따라 자동 재로딩하는 용도의 MessageSource 구현체
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
// 설명. 다국어 메시지를 읽어올 properties 파일의 파일 이름 설정
messageSource.setBasename("section03/properties/subsection02/i18n/message");
// 설명. 불러온 메시지를 지정 시간 동안 캐싱(초 단위)
messageSource.setCacheSeconds(10);
// 설명. 기본 인코딩 셋 설정
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
../i18n
- message_ko_KR.properties
- message_ko_KR.properties
...