IoC(제어의 역전)
- 클래스는 개발자가 만들고 클래스의 인스턴스는 프레임워크가 WAS가 만들어서 일반적인 프로그래밍의 흐름의 반대로 수행되는 것
1.Factory Method Pattern 실습
1) Temp 클래스 생성
public class Temp {
private int num;
private String name;
public Temp(int num, String name) {
super();
this.num = num;
this.name = name;
}
public Temp() {
super();
// TODO Auto-generated constructor stub
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Temp [num=" + num + ", name=" + name + "]";
}
}
3) Main 메소드를 소유한 main 클래스를 만들고 Temp 클래스 사용
public class Main {
public static void main(String[] args) {
Temp temp = new Temp();
temp.setName("Lee");
temp.setNum(1);
System.out.println(temp);
}
}
- 사용자가 만든 클래스를 가지고 직접 생성자를 호출해서 인스턴스를 만들고 사용
2.Factory Method Pattern
- 클래스의 인스턴스를 new를 직접 호출해서 생성하지 않고 다른 클래스의 메소드를 이용해서 생성하는 방식
- 만드는 과정이 복잡하거나 디자인 패턴이나 기타코드를 클래스에 추가하고자 하는 경우 사용
3.실습
1) Factory 클래스로 사용할 클래스를 추가
- TempFactory 클래스
// Temp 클래스의 Factory 클래스
public class TempFactory {
// Temp 의 Factory 메소드
public static Temp create() {
return new Temp();
}
}
2) Main 클래스 메소드 수정
public class Main {
public static void main(String[] args) {
Temp temp = TempFactory.create();
temp.setName("Lee");
temp.setNum(1);
System.out.println(temp);
}
}
클래스는 내가 만들었지만 실제 클래스는 Factory 클래스가 만들어주고, 실제쓰는것은 Factory 클래스에서 주는걸 쓴다.
4.Singleton 패턴
- 어떤 클래스가 인스턴스를 1개만 만들수 있도록 된 디자인 패턴
- 서버 쪽의 클래스들은 대부분의 경우 여러개의 인스턴스를 만들지 않고 하나의 인스턴스가 스레드를 이용해서 클라이언트 들의 요청을 처리하도록 해야 하는 경우가 대부분이고
메소드(함수) : Server는 20줄 이하로
변수 -> 함수 -> 클래스,객체
클래스, 객체 지향은 무겁지만. 안정성이 높다. .
함수만는 객체지향보다는 가볍지만 안정성이 낮다.한개만 만들어서 공유 한다 - static
Spring java application project 생성
1. project 생성
- [file] - [new] - [other] - [spring legacy project] 를 선택하고 [simple spring maven]
2.디렉토리가 생성되지 않은 경우
1) maven 프로젝트로 변환
- 프로젝트를 선택하고 마우스 오른쪽을 누른 후 [configure] - [convert to maven project]
2) pom.xml 파일에 붙여 넣기
<!-- 이 코드를 pom.xml 파일에 붙여 넣습니다 -->
<!-- 자주 사용하는 코드를 프로퍼티로 설정해놓은 태그 -->
<!-- 프로그램에서 변수를 만드는 것과 유사 -->
<!-- 자주 사용하는 버전들의 이름을 변수로 등록해 두는 것이 Properties 입니다. -->
<properties>
<!-- 자바 버전 -->
<java.version>1.6</java.version>
<!-- 소스코드와 출력되는 문자열을 인코딩 설정 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring 버전 4.0.1, 5.0.7 버전 변경 -->
<spring-framework.version>5.0.7.RELEASE</spring-framework.version>
<!-- Hibernate / JPA 버전 -->
<hibernate.version>4.2.1.Final</hibernate.version>
<!-- Log 라이브러리 버전 -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
<!-- Test 라이브러리 버전 (여긴 변경 최근 4.12) -->
<junit.version>4.12</junit.version>
</properties>
<!-- 중앙 저장소 이외에서 다운로드 받아야 할 때 설정: 다운로드 받는 서버를 설정 -->
<!-- 의존성 라이브러리 설정 -->
<dependencies>
<!-- Spring 기본 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Sprng 트랜잭션 처리 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logg 기록 라이브러리 설정 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<!-- 런타임이 실행일때 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- 스프링 테스트 - Test 할 때만 존재하고 배포할때는 자동으로 없어진다. -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3) 속성을 2개 갖는 클래스를 생성
- 디렉토리가 만들어진 경우에는 src/main/java 라는 디렉토리에 생성하고 그렇지 않은 경우는 root 디렉토리에 생성
- 디렉토리가 없는 경우는 프로젝트를 생성
public class Item {
private int num;
private String name;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Item [num=" + num + ", name=" + name + "]";
}
}
Spring 의 Bean Container
- Spring에서는 Spring이 제어권을 가지고 생성하고 관계를 설정하는 객체를 Spring Bean 이라고 한다.
- Bean이 Spring이 객체를 생성하고 관리하는 제어의 역전이 적용된 객체
- Bean Container를 만드는 방법
1.annotation을 이용하는 방법
1) 설정
- 클래스를 만들고 클래스 위에 @Configuration 어노테이션을 추가
- 인스턴스를 생성해서 리턴하는 메소드 위에 @Bean 어노테이션을 추가
2) 사용
AnnotationConfigApplicationContext 변수명 = new AnnotationConfigApplicationContext(앞에서만든 클래스이름.class);
인스턴스이름 = 변수명.getBean("메소드이름",메소드가 리턴하는클래스이름.class);
- 이렇게 만들면 싱글톤을 적용하지 않아도 자동으로 싱글톤 패턴의 객체가 리턴된다.
3) 실습
- Factory 클래스의 역할을 수행할 클래스를 생성 - Factory 클래스
// Spring의 Bean을 생성해주는 클래스라는 어느테이션
@Configuration
public class Factory {
// Bean을 만들어주는 메소드라는 어노테이션
// 이 메소드는 매번 Item 인스턴스를 만들어서 리턴하는 것이 아니고
// 처음 1개를 만들고 다음부터는 이 메소드를 호출하면 만들어지 것을 리턴
@Bean
public static Item create() {
return new Item();
}
}
- Main 메소드를 소유한 클래스를 만들어서 인스턴스를 만든 후 테스트 - SpringMain 클래스
public class SpringMain {
public static void main(String[] args) {
// SpringContainer 클래스 객체 만들기
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Factory.class);
// Bean 생성 메소드를 호출해서 Bean을 생성
// Factory 클래스의 create 라는 메소드를 이용해서 인스턴스를 생성하고 리턴
Item item1 = context.getBean("create", Item.class);
item1.setNum(1);
item1.setName("사과");
System.out.println(item1);
// item1과 2의 해시코드 출력
System.out.println(item1.hashCode());
Item item2 = context.getBean("create", Item.class);
item2.setNum(2);
item2.setName("배");
System.out.println(item2);
System.out.println(item2.hashCode());
}
}
item1과 item2의 해시코드가 동일하다
Factory 클래스의 Bean이 붙은 클래스의 메소드는 계속호출되지 않고 맨처음 한번만 호출하고다음부터는 이전에 만들어진 객체를 이용한다
@Configuration
public class Factory {
//Bean을 만들어주는 메소드라는 어노테이션
@Bean
public static Item create() {
// Bean이 붙은 클래스의 메소드는 계속호출되지 않고 맨처음 한번만 호출하고다음부터는 이전에 만들어진 객체를 이용한다
return new Item();
}
}
- main 메소드를 소유한 클래스를 만들어서 인스턴스를 만든 후 테스트
2.XML을 이용하는 방법 : 현재까지는 이 방법을 많이 사용
1) spring bean configuration 파일을 추가
2) 객체를 생성하는 태그를 설정
클래스 경로에 해당하는 객체를 생성해서 리턴 - 싱글톤
<bean id="아이디" class="클래스 경로" />
3) 사용
GenericXmlApplicationContext 변수명 = new GenericXmlApplicationContext(xml 파일 경로);
인스턴스이름 = 변수명.getBean("아이디", 메소드가 리턴하는클래스이름.class);
4) 실습
- spring bean configuration 파일추가 - applicationcontext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- domain.Item 이라는 클래스의 객체를 만들어주는 태그 -->
<bean id="item" class="domain.Item"/>
</beans>
- Xml 이용 - main 클래스 변경
public class SpringMain {
public static void main(String[] args) {
//xml을 이용하는 방법
GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:applicationcontext.xml");
// Bean 생성 메소드를 호출해서 Bean을 생성
// Factory 클래스의 create 라는 메소드를 이용해서 인스턴스를 생성하고 리턴
// xml 파일을 이용할 때는 id를 기재
Item item1 = context.getBean("item", Item.class);
item1.setNum(1);
item1.setName("사과");
System.out.println(item1);
// item1과 2의 해시코드 출력
System.out.println(item1.hashCode());
Item item2 = context.getBean("item", Item.class);
item2.setNum(2);
item2.setName("배");
System.out.println(item2);
System.out.println(item2.hashCode());
}
}
3.bean 태그의 속성
1) class
- 생성할 인스턴스의 class - 패키지 이름 까지 포함시켜야 한다.
2) id
- 외부에서 인스턴스를 가져다가 사용하기 위한 이름
- 생략하면 클래스이름 뒤에 #0을 붙입니다.
3) init
- method : 인스턴스를 생성할 때 호출되는 메소드
4) destroy
- method : 인스턴스가 소멸될 때 호출되는 메소드
5) lazy-init(지연생성)
- true를 설정하면 처음부터 만들어지지 않고 처음 사용할 때 만들어진다.
- 클라이언트 프로그램을 제작할 때 사용
- lazy-init이 false 이면 프로그램이 실행될 때 전부 만들어두고 실행
6) scope
- web에서만 설정하는 것으로 기본은 singleton이고 호출할 때 마다 생성하는 prototype 이나 request, session 등의 scope를 설정하는 것이 가능