spring 01 - 프레임워크 시작하기
프레임워크(Framework) 정의
- 사전적 의미 : 어떤 것을 구성하는 구조 또는 뼈대
- 소프트웨어적 의미 : 기능을 미리 클래스나 인터페이스 등으로 만들어 제공하는 반제품 적 형태
장점
- 일정한 기준에 따라 개발이 이루어지므로 개발 생산성과 품질이 어느정도 보장된 애플리케이션을 개발할 수 있다.
- 개발 후 유지보수 및 기능의 확장성에서도 고품질을 보장
스프링 프레임워크
- 자바 웹 애플리케이션 개발을 위한 오픈 소스 프레임워크다
- EJB(Enterprise Java Bean) 보다 가벼운 경량 프레임 워크
컨테이너(Container)
- '톰캣 = 서블릿 컨테이너' 라고 부르는데, 톰캣을 실행하면 서블릿의 생성, 초기화, 서비스 실행, 소멸에 관한 모든 권한을 가지고 서블릿을 관리하기 때문이다
- 스프링은 애플리케이션에서 사용되는 여러가지 빈(클래스 객체를)을 개발자가 아닌 스프링이 권한을 가지고 직접 관리하게 된다.
특징
- EJB보다 가볍고, 배우기 쉬우며, 경량 컨테이너의 기능을 수행한다
- 제어 역행(IoC, Inversion of Control) 기술을 이용해 애플리케이션 간의 느슨한 결합을 제어한다
- 의존성 주입(DI, Dependency Injection) 기능을 지원한다
- 관점 지향 (AOP, Aspect-Oriented Programming) 기능을 이용해 자원 관리한다
- 영속성과 관련된 다양한 서비스를 지원한다
- 수많은 라이브러리와의 연동 기능을 지원한다
용어 정리
- 의존성 주입 : 클래스 객체를 개발자가 코드에서 직접 생성하지 않고, 프레임워크가 생성하여 사용하는 방법
- 제어 역행 : 서블릿이나 빈 등을 개발자가 코드에서 직접 생성하지 않고, 프레임 워크가 직접 수행하는 방법
- 관점 지향 : 핵심 기능 외 부수 기능들을 분리해 구현함으로써 모듈성을 증가시키는 방법
- 자바 웹 애플리케이션 개발을 위한 오픈 소스 프레임워크다
- EJB(Enterprise Java Bean) 보다 가벼운 경량 프레임 워크
컨테이너(Container)
- '톰캣 = 서블릿 컨테이너' 라고 부르는데, 톰캣을 실행하면 서블릿의 생성, 초기화, 서비스 실행, 소멸에 관한 모든 권한을 가지고 서블릿을 관리하기 때문이다
- 스프링은 애플리케이션에서 사용되는 여러가지 빈(클래스 객체를)을 개발자가 아닌 스프링이 권한을 가지고 직접 관리하게 된다.
특징
- EJB보다 가볍고, 배우기 쉬우며, 경량 컨테이너의 기능을 수행한다
- 제어 역행(IoC, Inversion of Control) 기술을 이용해 애플리케이션 간의 느슨한 결합을 제어한다
- 의존성 주입(DI, Dependency Injection) 기능을 지원한다
- 관점 지향 (AOP, Aspect-Oriented Programming) 기능을 이용해 자원 관리한다
- 영속성과 관련된 다양한 서비스를 지원한다
- 수많은 라이브러리와의 연동 기능을 지원한다
용어 정리
- 의존성 주입 : 클래스 객체를 개발자가 코드에서 직접 생성하지 않고, 프레임워크가 생성하여 사용하는 방법
- 제어 역행 : 서블릿이나 빈 등을 개발자가 코드에서 직접 생성하지 않고, 프레임 워크가 직접 수행하는 방법
- 관점 지향 : 핵심 기능 외 부수 기능들을 분리해 구현함으로써 모듈성을 증가시키는 방법
스프링의 주요 기능
의존성 주입
- 연관관계를 개발자가 직접 코딩을 통해 컴포넌트(클래스)에 부여하는 것이 아니라 컨테이너가 연관 관계를 직접 규정하는 것
- 코드에서 직접적인 연관 관계가 발생하지 않으므로 각 클래스들의 변경이 자유로워진다
-> 강한 결합과 약한 결합
서로 관련있는 기능들은 강하게 결합(tightly coupled)하고, 관련이 없는 기능들은 약하게 결합(loosely coupled) 해야 한다
자바 코드로 게시판 구현시
- DAO 클래스에서 오라클과 연동해 게시판 기능을 구현하고 있는데, 오라클에서 MySql로 DB 변경시 DAO 클래스의 기능을 일일이 변경해야 하고, 더 나아가 DAO 클래스를 사용하는 Service 클래스의 기능도 변경해야 할 수도 있음
-> 따라서 자바 코드에서 직접 객체를 생성해 사용하는 것은 복잡한 문제를 일으킬 가능성이 농후
의존성 주입을 적용한 게시판
- 의존성 주입의 장점
- 클래스들 간의 의존 관계를 최소화 하여 코드를 단순화 가능
- 애플리케이션을 더 쉽게 유지 관리 가능
- 기존의 구현 방법은 개발자가 코드로 객체의 생성과 소멸을 제어했지만, 의존성 주입시 객체의 생성, 소멸, 객체간의 의존관계를 컨테이너가 제어
- 제어의 역전(Inversion Of Control)
- 기존 코드에서는 개발자가 직접 객체를 제어했지만 스프링 프레임 워크에서는 객체의 제어를 스프링이 직접 담당한다
-IoC의 종류도 여러가지 - 일반적으로 스프링에서는 DI로 IoC의 기능을 구현하므로 IoC보다는 DI라는 용어를 더 많이 사용한다
- 스프링의 의존성 주입 방법
- 생성자에 의한 주입
- setter에 의한 주입
setter로 의존성 주입하기
- 추상 메소드 작성하기
package com.sping.ex02;
public interface PersonService {
// 1. 추상 메소드로 작성
public void sayHello();
}
- 구현클래스(setter 작성)
package com.sping.ex02;
// 2. 구현 클래스 작성
public class PersonServiceImpl implements PersonService {
private String name;
private int age;
// 3. 값 받을 setter 작성
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
// 4. 오버라이드
@Override
public void sayHello() {
System.out.println("이름 : " + name);
System.out.println("나이 : " + age);
}
}
- person.xml 짜기(값 설정)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- class : 연결할 파일 경로 지정 -->
<bean id="personService02" class="com.sping.ex02.PersonServiceImpl">
<!-- 넣을 변수명과 값 작성 -->
<property name="name">
<value>홍길순</value>
</property>
<property name="age">
<value>20</value>
</property>
</bean>
</beans>
- xml에서 설정한 값을 personService를 통해 받아오기
package com.sping.ex02;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class PersonTest2 {
public static void main(String[] args) {
BeanFactory factory =
new XmlBeanFactory(new FileSystemResource("person.xml"));
// 값을 설정한 id 값 받아오기
PersonService person = (PersonService) factory.getBean("personService02");
// 실행
person.sayHello();
}
}
생성자로 의존성 주입하기
- 추상 메소드 작성
package com.spring.ex03;
// 생성자에 의한 명시
public interface PersonService {
// 1. 추상 메소드 명시
public void sayHello();
}
- 구현클래스(생성자) 만들기
package com.spring.ex03;
public class PersonServiceimpl implements PersonService{
private String name;
private int age;
// 기본 생성자
public PersonServiceimpl() {}
// 생성자 만들기
public PersonServiceimpl(String name) {
this.name = name;
}
public PersonServiceimpl(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public void sayHello() {
System.out.println("이름 : " + name);
System.out.println("나이 : " + age);
}
}
- person.xml 짜기(값 설정)
<bean id="personService03" class="com.spring.ex03.PersonServiceimpl">
<!-- 생성자 구문. 태그 속에 value로 값 보냄 -->
<constructor-arg value="이순신" />
<!-- 위 아래 어느 모양이라도 상관 없다 -->
<constructor-arg value="23"></constructor-arg>
</bean>
- xml에서 설정한 값을 personService를 통해 받아오기
package com.spring.ex03;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class PersonTest {
public static void main(String[] args) {
// xml에 작성한 값 가져오기(bean 자료 생성)
BeanFactory factory =
new XmlBeanFactory(new FileSystemResource("person.xml"));
PersonService person = (PersonService) factory.getBean("personService03");
person.sayHello();
}
}
만약 xml 에서<constructor-arg value="이순신" />
이것만 값을 보내도 나이 없이 이름만 잘 출력된다.
이런 식으로(근데 속성은 있고 값이 없으니 안 예쁘다)
3번 xml을 이런식으로 작성해주고
<bean id="personService03" class="com.spring.ex03.PersonServiceimpl">
<!-- 생성자 구문. 태그 속에 value로 값 보냄 -->
<constructor-arg value="이순신" />
<constructor-arg value="33"></constructor-arg>
</bean>
<!-- id 값은 고유 넘버. 겹치면 안된다 -->
<bean id="personService03.1" class="com.spring.ex03.PersonServiceimpl">
<constructor-arg value="이수영" />
</bean>
4번을 이런식으로 작성할 수도 있다.
package com.spring.ex03;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class PersonTest {
public static void main(String[] args) {
// xml에 작성한 값 가져오기(bean 자료 생성)
BeanFactory factory =
new XmlBeanFactory(new FileSystemResource("person.xml"));
PersonService person = (PersonService) factory.getBean("personService03");
person.sayHello();
System.out.println();
PersonService person1 = (PersonService) factory.getBean("personService03.1");
person1.sayHello();
}
}
lazy-init 사용해보기
기본적으로 Spring의 ApplicationContext 구현은 초기화 프로세스에서 모든 싱글톤 빈을 생성 및 설정하게 된다.
어떤 이유로 특정 bean이 늦게 초기화되기를 원한다면 lazy-init 을 사용하여 조정할 수 있다.
lazy-init 은 "true", "false", "default" 세 가지의 옵션을 가진다. default 는 spring 의 기본 동작에 맞게 bean 을 생성하며 기본 동작은 false 이다. true 로 설정할 경우 나중에 Bean 을 생성하게 된다.
- lazy.xml에 속성 설정하기
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="firstBean" class="com.spring.ex05.First" lazy-init="false" />
<bean id="secondBean" class="com.spring.ex05.Second" lazy-init="true" />
<bean id="thirdBean" class="com.spring.ex05.Third" lazy-init="default" />
</beans>
- 사용 할 세개의 클래스 작성하기
"First.java"
package com.spring.ex05;
public class First {
public First() {
System.out.println("First 생성자 호출");
}
}
"Second.java"
package com.spring.ex05;
public class Second {
public Second() {
System.out.println("Second 생성자 호출");
}
}
"Third.java"
package com.spring.ex05;
public class Third {
public Third() {
System.out.println("Third 생성자 호출");
}
}
- 실행 클래스 작성하기
package com.spring.ex05;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class LazyTest {
public static void main(String[] args) {
ApplicationContext context =
new FileSystemXmlApplicationContext("lazy.xml");
System.out.println("SecondBean 얻기");
context.getBean("secondBean");
}
}
분명 secondBean을 getBean 해주었음에도 lazy 설정에서true
즉 나중에 Bean을 생성하겠다 해주었기 때문에 출력결과가 위와 같이 나오는 모습을 확인 할 수 있었다.
Author And Source
이 문제에 관하여(spring 01 - 프레임워크 시작하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@cyhse7/spring-01-프레임워크-시작하기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)