일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- URIMalformedURI
- jdk
- NewServer
- tomcat
- Eclipse
- 일급객체
- curryr
- ArrayLike
- LexicalScope
- javacversion
- AOP
- Spring
- Annotation
- URI$MalformedURIException
- REGEXP_COUNT
- joinpoint
- xml
- SpringFramework
- AfterReturnning
- ModulesPath
- map
- URIMalformedURI오류
- URIMalformedURIException
- TargetObject
- oracle
- springversion
- SQL
- javaversion
- 자유변수
- ProjectFacets
- Today
- Total
잼's Tech
[SPRING] DI 본문
[SPRING] DI
DI(의존성 주입: Dependency Injection)
Spring에서의 Di란 클래스 사이의 의존관계를 컨테이너가 자동으로 맵핑해주는 것이다.
예를 들면
이런식으로 개발자가 직접 의존성을 만든다.
하지만, Spring에서는
이런 식으로 config.xml을 읽어 컨테이너에 bean으로 생성 후 필요할 때마다 bean 객체를 꺼낸 후 자동적으로 의존성 주입을 컨테이너가 해준다.
Spring에서의 다양한 Di 설정 방법에 대하여 배워보자
크게 XML, Annotation 방식 2가지로 나뉘어진다.
이해를 돕기 위해 이런 클래스와 인터페이스를 만들어 놓았다.
<코드>
// Car interface
public interface Car { void take(String s); }
// Person Class
import com.my.di.ui.Car;
public class Person {
private Car car;
int age;
public Person() {};
public Person(Car car, int age) { this.car = car; this.age = age; }
public Car getCar() { return car; }
public void setCar(Car car) { this.car = car; }
public void take(String name) { car.take(name); }
@Override
public String toString() { return "Person [car=" + car + " / age=" + age + "]"; }
}
// Taxi Class
public class Taxi implements Car{
@Override
public void take(String s) { System.out.println(s+" take a Taxi"); }
}
// Bus Class
public class Bus implements Car{
@Override
public void take(String s) { System.out.println(s+" take a Bus"); }
}
※ 보다시피 Taxi와 Bus는 Car 인터페이스를 구현한 것이다. 그렇기에 사용 시 Bus를 넣어줄 것인지 Taxi를 넣어줄 것인지 명시를 해줘야한다. 만약 그렇지 못한다면 java.lang.IllegalStateException가 발생하게 된다.
1) XML 방식
- Constructor -Arg
//config.xml
<bean id = "bus" class = "com.my.di.ui.Bus"></bean>
<bean id = "taxi" class = "com.my.di.ui.Taxi"></bean>
<bean id = "Person" class = "com.my.di.entity.Person">
<constructor-arg index="0" ref="bus" />
<constructor-arg index="1" value="20" />
</bean>
객체는 기본적으로 ref를 사용하여 주입하고
기본형은 value를 사용한다.(string, int 등등)
위 방식은 생성자가 필요하다. ex) public Person(Car car, int age)
- Property
//config.xml
<bean id="bus" class="com.my.di.ui.Bus"></bean>
<bean id="taxi" class="com.my.di.ui.Taxi"></bean>
<bean id="Person" class="com.my.di.entity.Person">
<property name="car" ref="taxi" />
</bean>
- p 태그
p 태그 사용시 xml에 p 태그 DTD가 필요하다.
<beans xmlns=> 안에 넣어주자
xmlns:p="http://www.springframework.org/schema/p
//config.xml
<bean id="bus" class="com.my.di.ui.Bus"></bean>
<bean id="taxi" class="com.my.di.ui.Taxi"></bean>
<bean id="Person" class="com.my.di.entity.Person" p:car-ref="bus" />
p 태그와 Property는 set 메서드를 사용하니 set 메서드가 필요하다.
- Untitled Text File 사용
Untitled Text File 사용시 당연히 File이 필요하고 그 파일의 경로가 필요하다.
파일의 경로는 context로 잡아주는게 편하다.
이를 위해 context DTD가 필요하다
xmlns:context="http://www.springframework.org/schema/context
//config.xml
<context:property-placeholder location="classpath:com/my/di/test/personlist.properties" />
<bean id="bus" class="com.my.di.ui.Bus"></bean>
<bean id="taxi" class="com.my.di.ui.Taxi"></bean>
<bean id="Person" class="com.my.di.entity.Person">
<property name="car" ref="taxi" />
<property name="age" value="${person1.age}" />
</bean>
//personlist.properties file
person1.age=22
2) Injection + XML 방식
Injection의 종류는 총 4가지가 있다.
//config.xml
<bean id="car" class="com.my.di.ui.Bus" />
<bean id="Person" class="com.my.di.entity.Person" />
우선 xml에 위와 같이 작성하고
Person Class에서
- Property Injection
//Person.java
@Autowired
private Car car;
- Setter Injection
//Person.java
@Autowired
public void setCar(Car car) {
this.car = car;
}
- 특정 메소드 Injection
//Person.java
//메소드를 직접 만들어주는 것
@Autowired
public void matchCar(Car car) {
this.car = car;
}
- 생성자 Injection
//Person.java
@Autowired
public Person(Car car){
this.car = car;
}
※ Autowired의 경우 넣을 수 있는 타입이 bean에 있다면 자동으로 넣어준다.
이때, 만약 Bus와 Taxi가 같이 있다면?
//config.xml
<bean id="bus" class="com.my.di.ui.Bus" />
<bean id="taxi" class="com.my.di.ui.Taxi" />
<bean id="person" class="com.my.di.entity.Person" />
java.lang.IllegalStateException가 뜰 것이다.
이때, 사용하는 것이
@Qualifier("bus"), @Resource(name="taxi") Annotation이다.
@Autowired
@Qualifier("bus")
public void setCar(Car car) {
this.car = car;
}
또는
@Autowired
@Resource(name="bus")
public void setCar(Car car) {
this.car = car;
}
※ 주의할 것은 생성자 Injection은 @Qualifier, @Resource가 사용이 안된다.
우선은 빈 값을 가지더라도 객체를 만들고 싶다면 @Autowired(required=false)를 사용하면 된다.
- Component-scan 방식
- bean을 일일이 등록해주지 않아도 된다.
- 역시 context DTD가 필요하다.
//config.xml
<context:component-scan base-package="com.my.di.ui, com.my.di.entity" />
자동적으로 패키지들을 읽으며 component가 붙은 클래스들을 bean으로 생성한다.
그렇기에 bean으로 올릴 객체들만 component Annotation을 붙여주면 된다.
이때 이름을 따로 안 준다면 클래스의 맨 앞글자를 소문자로 바꾸어 id 값으로 등록한다
ex) Class Person -> id: person
@Component
클래스
또는
@Component("줄 이름")
클래스
※ 알아두면 좋을 Value Annotation과 EL 태그
이것은 의존 객체 생성 시 변수에 값을 넣어주는 것이다.
@Value("#{'SPRINGkk' +' EL '}")
private String name = "";
3) Annotation 방식
- @Bean 사용
config.xml을 사용하지 않고 클래스와 Annotation을 이용하는 방식이다.
// di_config.java
@Configuration
public class di_config {
@Bean
public Person person() {
return new Person(taxi());
}
@Bean
public Taxi taxi() {
return new Taxi();
}
@Bean
public Bus bus() {
return new bus();
}
}
- ComponetScan 사용
// di_config.java
@ComponentScan({"com.my.di.ui, com.my.di.entity"})
@Configuration
public class di_config {}
// bean으로 올릴 클래스 위에 component를 올려줘야한다.
@Component("bus")
@Component()
- 사용 시
@ContextConfiguration(classes= {di_config.class})
public class 사용할 클래스 {
@Autowired
ApplicationContext context;
@Test
public void bean1() {
Person person = (Person)context.getBean("person");
person.take("jaem");
System.out.println(person.toString());
}
}
다양한 사용 방식
컨테이너가 의존 객체를 생성할 때 타입이 어떻게 되는지 알려줘야하는데
이때, 다양한 방법으로 알려줄 수 있다.
@ContextConfiguration(locations = "classpath:com/my/di/test/config.xml")
public class 사용할 클래스 {
@Autowired
ApplicationContext ctx;
@Test
public void bean1() {
// 타입에 맞추어 데이터 가져오기 1
Person person = (Person)ctx.getBean("person");
// 타입에 맞추어 데이터 가져오기 2
Person person = ctx.getBean(Person.class);
// 타입에 맞추어 데이터 가져오기 3
Person person = ctx.getBean("person",Person.class);
person.take("jaem");
System.out.println(person.toString());
}
}
컬렉션이 포함된 bean 객체
컬렉션에 대해 잘 모른다면
https://jaem-tech.tistory.com/18
[JAVA] 컬렉션(Collection) 프레임워크
컬렉션? 여러 자료를 효율적으로 보관 및 처리하기 위한 자료구조 배열의 단점을 보완 사이즈가 동적 어떤 자료형이라도 상관 없음 컬렉션 프레임워크? 여러 자료를 효율적으로 관리하기 위한
jaem-tech.tistory.com
을 참고하자.
- List
//Person.java
private List<String> names;
//config.xml
<bean id="person" class="com.my.di.entity.Person">
<property name="names">
<list>
<value>Spring</value>
<value>AOP</value>
<value>DI</value>
</list>
</property>
</bean>
// Person.java
private List<Human> humans;
// Human.java
int age;
String name;
// config.xml
<bean id="person" class="com.my.di.entity.Person">
<property name="humans">
<list>
<bean class="com.my.di.humans">
<property name="age" value="30" />
<property name="name" value="jaem" />
</bean>
<bean class="iaccess.di.entity.Person">
<property name="age" value="50" />
<property name="name" value="hong" />
</bean>
</list>
</property>
</bean>
사용 시
Person person = context.getBean(Person.class);
List<String> list = person.getNames();
// 1) forEach + lamda
list.forEach(s->System.out.println(s));
// 2) enhencede for
for(String value : list) {
System.out.println(value);
}
// 3) Iterator
Iterator<String> lst = list.iterator();
while(lst.hasNext()) {
System.out.println(lst.next());
}
- Map
//Person.java
private Map<String, Integer> ages;
//config.xml
<bean id="person" class="com.my.di.entity.Person">
<property name="ages">
<map>
<entry key="Kim" value="10" />
<entry key="Lee" value="20" />
<entry key="Ahn" value="30" />
</map>
</property>
</bean>
사용 시
Person person = context.getBean(Person.class);
Map<String, Integer> ages = person.getAges();
// 1) enhencede for
for(Map.Entry<String,Integer> entry : ages.entrySet()) {
System.out.println("KEY : " + entry.getKey() + ", VALUE : " + entry.getValue());
}
// 2) Iterator set(keyset)
Iterator<String> keys = ages.keySet().iterator();
while(keys.hasNext()) {
String key = keys.next();
System.out.println("key : " + key + ", value : " + ages.get(key));
}
// 3) lamda
ages.forEach((key,value) -> System.out.println("key: " + key + " | value: " + value));
ages.entrySet().forEach(entry -> System.out.println("key: " + entry.getKey() + " | value: " + entry.getValue()));
ages.keySet().forEach(key -> System.out.println("key: " + key));
ages.values().forEach(value -> System.out.println("value : " + value));
- Set
//Person.java
private Set<String> emails;
//config.xml
<bean id="person" class="com.my.di.entity.Person">
<property name="emails">
<set>
<value>kor@naver.com</value>
<value>eng@naver.com</value>
<value>eng@naver.com</value>
</set>
</property>
</bean>
사용 시
Person person = context.getBean(Person.class);
Set<String> set = person.getEmails();
Iterator<String> it = hs.iterator();
// 1) enhencede for
for(String s : set) {
System.out.println(s);
}
// 2) Iterator
while(it.hasNext()) {
System.out.println(it.next());
}
// 3) lamda
set.forEach(s-> System.out.println(s));
'FRAME WORK > SPRING' 카테고리의 다른 글
[SPRING] AOP 적용 (0) | 2021.08.18 |
---|---|
[SPRING] AOP 이론 (0) | 2021.08.13 |