[@Bean]
: 메서드-레벨 애너테이션으로 <bean/>에서 제공하는 일부 속성을 지원함
: @Configuration-annoted 또는 @Component-annoted 클래스에서 사용이 가능함
: 대상 빈이 하나의 생성자만 정의하는 경우 @Autowired 지정할 필요가 없음
빈 선언)
: 메서드에 @Bean 애너테이션을 추가해 Bean으로 선언 가능
: 빈 정의가 있는 인터페이스를 구현해 bean configuration 설정도 가능
(' implements 빈_정의가_있는_인터페이스명 '을 클래스에 붙여 설정 가능)
(1)
@Configuration
public class AppConfig {
//빈 선언
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
(2)
public interface BaseConfig {
@Bean
default TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
//빈을 가진 인터페이스를 구현해 configuration 설정
@Configuration
public class AppConfig implements BaseConfig {
}
빈 의존성)
: @Bean 애너테이션이 추가된 메서드는 빈을 구축하는데 필요한 의존성을 나타내는데 매개 변수를 사용할 수 있음
(메서드 매개변수를 사용함으로서 종속성 구체화 가능)
* 메서드명() >> 메서드명(매개변수) 이용 가능
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
수명주기 콜백 수신)
: @Bean은 일반 수명 주기 콜백을 지원하고 @PostConstruct 및 주석 사용이 가능함
public class BeanOne {
public void init() {
// initialization logic
}
}
public class BeanTwo {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init") //임의의 초기화 메서드 initMethod 지정 지원
public BeanOne beanOne() {
return new BeanOne();
}
@Bean(destroyMethod = "cleanup") //임의의 소멸 콜백 메서드 destroyMethod 지정 지원
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
[@Configuration]
: 해당 객체가 bean definitions의 소스임을 나타내는 애너테이션
: @Bean-annoted 메서드를 통해 bean을 선언
: 클래스의 @Bean 메서드에 대한 호출을 사용해 bean 사이의 의존성 정의 가능
Bean 사이 의존성 주입)
: 빈간 의존성을 주입하는 것은 클래스 @Bean 내에서 메서드가 선언된 경우만 작동하며 일반 @Component 클래스를 사용해 선언은 불가능함
@Configuration
public class AppConfig {
@Bean
public BeanOne beanOne() {
return new BeanOne(beanTwo()); //beanTwo와 의존 관계
}
@Bean
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
Java를 기반으로 설정된 환경에서 내부적으로 작동하는 방식에 대한 정보)
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao()); //(1) clientDao() 메서드 호출
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao()); //(2) clientDao() 메서드 호출
return clientService;
}
@Bean
public ClientDao clientDao() { //(2) ClientDatoIml 새 인스턴스를 만들고 반환
return new ClientDaoImpl();
}
}
문제점 - clientService1,2에서 clientDao 메서드를 모두 호출하기에 각 인스턴스가 존재해야 하지만 빈은 기본 싱글톤 범위를 가짐
: 문제점 해결을 위해 하위 클래스의 하위 메서드는 상위 메서드를 호출하고 새 인스턴스를 만들기 전 먼저 컨테이너에 캐시된(범위 지정) bean이 있는지 확인이 필요함
Java 기반 구성 작성)
: Spring의 Java 기반 구성 기능을 사용할 경우 주석 사용이 가능하므로 구성의 복잡성을 줄일 수 있음
@import 애너테이션 사용
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class) //다른 구성 클래스에서 @Bean definitions를 가져올 수 있음
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
: 컨텍스트를 인스턴스화할 때 둘 다 지정할 필요 없이 ConfigA.class 예제와 같이 명시적으로 제공만 하면 됨
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// now both beans A and B will be available...
A a = ctx.getBean(A.class);
B b = ctx.getBean(B.class);
}
: @Configuration 접근 방식은 생성하는 동안 잠재적으로 많은 수의 클래스를 기억할 필요 없이 하나의 클래스만 처리하면 되기 때문에 컨테이너 인스턴스화를 단순화함
가져온 @Bean 정의에 의존성 주입
: 클래스 사용시 @Configuration Java 컴파일러는 다른 빈에 대한 참조가 유효한 Java 구문이어야 한다는 점에서 구성 모델에 제약을 둠
@Configuration
public class ServiceConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
<해결방법>
: @Bean은 종속성을 설명하는 임의의 수의 매개변수를 가질 수 있기에 빈 의존성을 설명하는 임의 개수 파라미터를 가질 수 있음
: @Autowired 및 @Value 주입 및 다른 bean과 동일한 기능을 사용할 수 있음
@Configuration
public class ServiceConfig {
@Autowired
private AccountRepository accountRepository;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
private final DataSource dataSource;
public RepositoryConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
'공부 자료 > Spring' 카테고리의 다른 글
[Spring Core] 컴포넌트 스캔 & 필터 (0) | 2022.10.15 |
---|---|
[Spring Core] Component Scan (0) | 2022.10.15 |
[Spring Core] 빈 스코프(Bean Scope) (0) | 2022.10.13 |
[Spring Core] 빈(Bean) (1) | 2022.10.13 |
[Spring Core] 스프링 컨테이너(Spring Container), 스프링 컨텍스트(Spring Context) (0) | 2022.10.13 |