2018-6-21 스프링 빈
발표자료
빈이란? 빈객체의 등록
- 스프링이 생성하는 객체를 빈(Bean)이라고 부른다. 이것에 대한 정보는 applicationContext.xml 파일 <bean>태그 안에 들어있다.
- <bean>태그의 속성은 id, name이 있는데, id는 빈 객체를 구분할 때 사용하는 이름, name은 빈객체를 생성할때 사용하는 클래스이다.
//applicatinoContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config/>
<bean id="member" class="domain.Member" scope="prototype"></bean>
</beans>
<bean id="greeter" class="domain.Greeter">
<property name="format" value="안녕하세요!"></property>
</bean>
Greeter greeter = new Greeter();
greeter.setFormat("%s, 안녕하세요");
//Main
public class Main {
public static void main(String[] args) {
// Bean객체를 생성
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationContext.xml");
// Bean객체를 제공
Greeter g1 = ctx.getBean("greeter", Greeter.class);
Greeter g2 = ctx.getBean("greeter", Greeter.class);
String msg = g.greet("gradle을 이용해서 빈객체를 생성");
System.out.println(msg);
ctx.close();
}
}
- 위의 bean태그를 등록을 하면, 스프링컨테이너가 동작을 할때, Greeter greeter = new Greeter()와 같은효과를 발휘?한다.
스프링은 객체 컨테이너
- 스프링의 핵심은 객체를 생성하고 초기화를 하는 것이다.
- GenericApplicationContext는 인터페이스이고, 그것의 밑에있는 3개의 Context가 구현체이다. (위의 메인문에서, applicationContext.xml을 읽어왔다.)
- GenericXmlApplicationContext : XML로부터 객체 설정 정보를 가지고 온다.
- AnnotaionConfigApplicationContext : 자바 어노테이션을 이용한 클래스로부터 객체설정정보를 가지고 온다.
스프링은 별도의 설정이 하지 않으면 한개의 빈객체만을 생성을 한다. 이를 싱글톤이라고 한다.
의존이란?
public class CarRegisterService {
private CarDao carDao = new CarDao();
public void regist(String name) {
Car car = carDao.selectByName(name);
carDao.insert(car);
}
}
- CarRegisterService의 경우 CarDao객체를 생성을 해서, 역할을 수행을 하고 있다. 클래스에서 다른클래스의 메서드를 실행을 하는 경우 의존한다고 표현을 한다.
- 의존을 하는 경우, 의존객체를 위의 경우처럼 직접 생성을 하면 좋지만, 유지보수 관점에서 힘들다.
- 어떻게 해야될까?
DI를 통한 의존 처리
public class CarRegisterService {
private CarDao carDao;
public CarRegisterService(CarDao carDao) {
this.carDao = carDao;
}
- DI(의존주입)는 의존하는 객체를 직접 생성하지않고, 생성자나 setter메서드를 통해 의존객체를 전달받는것이다.
CarDao carDao = new CarDao();
CarRegisterService regSvc = new CarRegisterService(carDao);
CarBuyService buySvc = new CarBuyService(carDao);
- 위의 코드에서 변경사항이 발생하면, carDao를 생성하는곳만 수정을 하면된다.
public class Assembler {
private CarDao carDao;
private CarRegisterService regSvc;
private CarBuyService buySvc;
public Assembler() {
carDao = new CarDao();
regSvc = new CarRegisterService(carDao);
buySvc = new CarBuyService(carDao);
}
public CarDao getCarDao() {
return carDao;
}
public CarRegisterService getRegSvc() {
return regSvc;
}
public CarBuyService getBuySvc() {
return buySvc;
}
}
- 위의 코드처럼 객체를 따로 생성을 하고, 주입을 하는 조립기 객체를 만든다.
- 조립기 객체를 만들고, get메서드를 이용을 해서 객체를 가지고온다.
스프링의 DI설정
- 이전에는 조립기를 이용을 해서 DI를 진행했지만, 스프링은 DI를 제공을 하는 조립기자체이다.
<bean id="carDao" class="dao.CarDao"></bean>
<bean id="carRegSvc" class="service.CarRegisterService">
<constructor-arg ref="carDao" />
</bean>
<bean id="carBuySvc" class="service.CarBuyService">
<constructor-arg ref="carDao" />
</bean>
- applicationContext파일에 미리 빈객체들을 등록을 시켜놓는다.
- <constructor-arg ref=”carDao” />를 통해 인자를 전달을 한다. 이름이 carDao인 객체를 생성자에 전달.
설정메서드 타입
- 인스턴스변수를 선언을 하고, get메서드, set메서드를 사용
- set메서드를 사용을 하는 경우, <property>태그를 사용하고 이 태그는 name속성과 ref속성이 있다. value속성을 이용하면 기본타입의 데이터를 전달할 수 있다.
- property의 name은 set메서드의 이름을 사용한다.
설정메서드 vs 생성자방식
- 생성자방식 : 빈객체를 생성하는 시점에 모든 의존객체가 주입
- 설정메서드방식 : property태그의 name속성을 통해 어떤 객체가 주입되는지 알 수 있다.
의존 자동주입
- @autowired어노테이션을 통해서 설정에 의존객체를 명시하지 않아도 스프링이 자동으로 필요한 빈객체를 생성을 한다.
- 즉 @Autowired를 사용안하면 노가다. 사용을 하면 굉장히 편하다.
<bean id="carDao" class="dao.CarDao"></bean>
<bean id="carRegSvc" class="service.CarRegisterService"></bean>
<bean id="carBuySvc" class="service.CarBuyService"></bean>
- 위와 같이 단순해진다.
- 설정에 <context:annotation-config />를 추가해야한다.
- @Autowired태그를 사용하면 constructor-arg태그나 property태그를 사용을 할 필요가 없다.
- @Autowired태그는 스프링타입을 이용해서 의존대상객체를 검색을 한다.
@Resource
- @Autowired어노테이션은 빈의 타입을 기준으로 검색을 한다. 반면 @Resource어노테이션은 빈의 이름을 기준으로 검색을 한다.
- 하지만 @Resource어노테이션은 메서드나 필드에만 적용이 가능하고, 생성자에는 적용이 안된다.
@Resource 어노테이션 적용순서
- name에서 속성한 빈객체를 찾는다.
- name속성이 없을경우 동일한 타입을 찾는다.
- name속성이 없고 동일한 타입을 갖는 빈 객체가 2개이상이면, 같은 이름을 가진 빈객체를 찾는다.
@Autowired vs @Resource
- @Autowired어노테이션은 required속성을 사용할 수 있다.
Java코드를 이용한 빈객체
- GenericXmlApplicationContext클래스 대신 AnnotaionConfigApplicationContext클래스를 이용을 해서 스프링 컨테이너를 생성을 한다.
@Configuration
public class JavaConfig {
@Bean
public CarDao carDao() {
return new CarDao();
}
@Bean
public CarRegisterService carRegSvc() {
return new CarRegisterService(carDao());
}
@Bean
public CarBuyService carBuySvc() {
return new CarBuyService(carDao());
}
}
- xml에서 설정을 하던 방법을 자바객체의 형태로 등록을 할 수 있다.
- xml설정은 빈객체를 스프링컨테이너가 직접생성을 하지만, 자바설정에서는 자바설정코드에서 직접객체를 생성한다.
- xml설정에서는 <context:annotation-config>설정을 추가해야 자동주입이 가능했지만, 자바설정파일에서는 별도의 설정파일이 필요가 없다.
ApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class)
빈라이프사이클과 범위
public class Main {
public static void main(String[] args) {
// 1. 컨테이너 초기화
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationContext.xml");
//2. 컨테이너 사용
Greeter g = ctx.getBean("greeter", Greeter.class);
String msg = g.greet("gradle을 이용해서 빈객체를 생성");
System.out.println(msg);
//3. 컨테이너 종료
ctx.close();
}
}
- 컨테이너초기화 : 빈객체의생성과 의존객체주입 및 초기화
- 컨테이너종료 : 빈객체의소멸
객체범위
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
Member member = context.getBean("member", Member.class);
Member member1 = context.getBean("member", Member.class);
System.out.println("member == member1" + member.equals(member1));
}
}
@Configuration
public class JavaConfig {
@Bean
@Scope("prototype")
public Member member() {
return new Member();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config/>
<bean id="member" class="domain.Member" scope="prototype"></bean>
</beans>
Written on June 21, 2018