[2022.12.29.목] 스프링 DI(의존성주입), AOP(관점지향), Maven
스프링
- 오픈소스 프레임워크
- 오픈소스 : 라이센스 무료, 가공/수익창출 허용
- 프레임워크 : 특정한 아이디(개발방식, 개발패턴, 아키텍처)의 구현체
- 라이브러리와 프레임워크
* 라이브러리 : 개발에 필요한(자주 사용되는) 기능의 구현체
필요한 기능이 구현되어 있는 라이브러리를 다운받아서 그 라이브러리의 기능을 사용한다.
* 프레임워크 : 개발방식, 개발 패턴의 구현체 (ex. ibatis)
해당 프레임워크에서 제시하는 방식에 맞게 클래스나 인터페이스, 환경설정 정보를 구성하면
프레임워크가 제공하는 기능을 제공받을 수 있다.
- Java 기반의 엔터프라이즈 애플리케이션 개발을 지원하는 프레임워크
- DI(의존성 주입)의 구현체
- 의존성 주입은 스프링의 가장 핵심적인 기능이다.
- 인터페이스를 이용해 클래스와 클래스 간의 결합을 느슨하게 유지하고, 의존성 주입으로 의존하는 객체를 주입하면, 코드의 변경없이 의존하는 객체를 변경할 수 있다.
- 즉, 확장성이 매우 뛰어난 애플리케이션을 개발할 수 있다.
- AOP(관점지향 프로그래밍)의 구현체
- 관점지향 프로그램은 핵심 기능으로부터 프로그램의 공통관심사항을 분리시키는 것이다.
- 관점: 코드를 핵심관심사항(핵심기능)과 공통관심사항(공통기능)으로 구분하는 것이다.
- 스프링의 AOP는 공통관심사항을 별도의 모듈(Advice와 Pointcut)로 개발하고, 공통관심사항이 적용될 대상과 시점을 지정하면 핵심기능이 구현된 메소드가 실행될 때마다 공통기능을 실행시킨다.
- 즉, 메소드에서 공통관심사항 코드를 제거할 수 있다. (중복 제거)
- 스프링은 객체를 생성하는 공장이다. ( Bean(객체) Factory. )
- 스프링은 객체를 조립한다. (객체 간의 의존관계를 분석해서 필요로 하는 객체를 주입한다.)
* 의존성 주입 (@Autowired)
UserDao 인터페이스를 구현한 UserOracleDao 구현클래스
UserController, OrderController는 인터페이스에 의존하고 있고, 이 안에서의 userDao가 가리키는 것은 UserOracleDao 안에 있는 UserDao를 가리킴 -> 재정의된 메소드 실행
근데, 오라클 데이터베이스에서 마리아 데이터베이스로 변경이 생길 때
마리아 데이터베이스도 UserDao 인터페이스를 구현
해당 인터페이스를 구현한 객체로 바꿔가면서 연결할 수 있음
단, 다음의 조건을 충족해야 함
1) Controller가 직접 객체를 만들면 안됨 (UserOracleDao, UserMariaDao같은 구체적인 클래스 이름이 등장하면 안돼)
2) 구체적인 구현클래스를 의존하지 않고, 인터페이스를 의존해야함 ( UserDao userDao; )
=> 코드를 하나도 건들지 않고 컨트롤러가 의존하는 객체를 변경할 수 있음 !!!
* 관점지향 프로그래밍 (@Aspect)
- 이렇게 하다보면, 핵심관심사항보다 공통관심사항을 호출하는 코드가 더 많아져버림
-> 그래서 분리를 해야돼
핵심관심사항을 남겨두고, 공통관심사항은 지워
공통관심을 밖으로 분리해서, 필요한 시점에 자동으로 외부에서 삽입되도록 하는 것
Advice안에 Target을 지정해서 메소드 실행을 적용할 대상 지정
위에서는 공통관심사항을 일반 클래스에 넣음 -> 사용하려면 호출을 해야됨
Advice 클래스 생성 - 공통관심사항을 구현 -> 얘가 공통기능을 실행
이 공통기능이 적용되어야 하는 타겟을 정해서 스프링 환경설정 파일에 적어놔
메소드를 호출하는 것이 아니라,
어떤 프로그램이 실행될 때마다 반드시 실행해야 하는 공통관심사항이 뭔지 Advice를 알려주는 것
* Advice 작성 예
-> @Aspect가 붙어있네? 그럼 스프링이 알아서 분석
-> 대상 메소드가 실행되기 전에, service 패키지 안에 있는 모든 Service 클래스에 있는 모든 메소드를 실행할 때마다 공통관심사항 메소드가 적용
-> 핵심기능이 구현된 코드에서 코드 변경없이 공통관심기능을 추가/삭제 -> 코드중복 제거, 핵심기능에 대한 유지보수, 재사용성
스프링 컨테이너
- 애플리케이션에서 사용되는 객체의 라이프사이클(객체 생성, 조립, 유지/관리)을 관리한다.
- 스프링 컨테이너의 종류
- BeanFactory
- spring-bean.jar에 포함되어 있는 스프링 컨테이너 인터페이스다.
- 객체 생성, 객체 조립과 같은 간단한 기능만 제공하는 스프링 컨테이너다.
- 구현클래스 : xmlBeanFactory - ApplicationContext
- spring-context.jar에 포함되어 있는 스프링 컨테이너 인터페이스다.
- 객체 생성, 객체 조립, 관점지향 프로그래밍 지원, 국제화, EJB 연동 등 다양한 기능을 제공하는 스프링 컨테이너다.
- 구현클래스 : ClasspathXmlApplicationContext, FilesystemXmlApplicationContext, GenericXmlApplicationContext, WebApplicationContext - webApplicationContext
- spring-web.jar에 포함되어 있는 스프링 컨테이너 인터페이스다.
- ApplicationContext 인터페이스와 기능은 유사하고, 웹 환경에 최적화되어 있는 스프링 컨테이너 인터페이스다.
- 구현클래스 : XmlWebApplicationContext
- BeanFactory
Maven
- 자바의 프로젝트 빌드 도구
- 프로젝트의 라이브러리 의존성, 소스 컴파일, 패키징, 배포 등의 작업을 자동화할 수 있다.
- 프로젝트 생성/관리하는 도구
- 메이븐 프로젝트는 pom.xml 파일을 포함하고 있다.
- pom.xml 파일은 프로젝트 정보를 표현하는 파일이다.
- pom.xml 파일은 프로젝트의 최상위 폴더에 위치하고 있다.
- pom.xml의 POM(Project Object Model : 메이븐에서 프로젝트를 표현하는 객체)을 설정하는 파일이다.
- pom.xml의 주요 구성 요소
- 프로젝트 정보
<groupId />
- 프로젝트를 생성하는 조직 또는 그룹명을 나타낸다.
- 보통 URL의 역순으로 지정한다.
<artifactId />
- 프로젝트의 고유한 아이디다. (보통 프로젝트명)
- 프로젝트 산출물의 고유한 아이디다.
<version />
- 애플리케이션의 버전을 나타낸다.
(SNAPSHOT - 개발단계)
<packaging />
- 프로젝트 패키징 유형을 나타낸다.
- jar, war, ear, pom 중 하나를 지정한다. 지정하지 않으면 jar
(jar - 자바 프로젝트 패키징, war - 웹 애플리케이션 프로젝트를 톰캣에 배포하려면 war로 패키징)
<name />
- 프로젝트 명
<description />
- 프로젝트에 대한 설명
<url />
- 프로젝트를 찾을 수 있는 URL
<properties />
- pom.xml에서 중복해서 사용되는 설정값을 지정한다. - 의존성 라이브러리 정보
- 의존성 라이브러리를 정의하는 부분
- 프로젝트에서 사용하는 라이브러리 정보를 정의한다.
- 라이브러리정보는 groupId, artifactId, version 정보가 필요하다. - 빌드/배포 정보
- 프로젝트의 빌드/배포와 관련된 설정정보를 정의하는 부분이다.
- 프로젝트 정보
- 메이븐 프로젝트는 pom.xml 파일을 포함하고 있다.
* spring-di/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 프로젝트 정보 -->
<groupId>com.sample</groupId>
<artifactId>spring-di</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- pom.xml 파일에서 사용되는 프로퍼티값(상수값)을 설정한다. -->
<properties>
<!-- 프로젝트의 자바버전을 정의한다. -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!--
로그출력을 지원하는 slf4j 라이브러리의 버전 정보를 상수로 정의한다.
<version>${slf4j.version}</version>와 같이 ${} 형식으로 값을 사용할 수 있다.
-->
<slf4j.version>1.7.25</slf4j.version>
</properties>
<!-- 프로젝트의 의존성 라이브러리를 정의한다. -->
<dependencies>
<!--
spring-context 라이브러리 의존성 정의
spring-context 라이브러리 의존성은 spring-core, spring-beans, spring-aop, spring-expression 라이브러리도 포함한다.
* 스프링을 이용해서 객체 생성, 의존성 주입, 관점지향 프로그래밍 실습이 가능하다.
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.24</version>
</dependency>
<!--
로그 출력(내부적으로 어떤 일이 진행되는지 표시)을 지원하는 라이브러리 의존성 정의
-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
</project>
* 스프링의 bean 설정파일 생성 (context-1.xml)
* context-1.xml
<bean> : 객체 생성
<property> : 객체 조립
* 각 객체에 setter 메소드가 있어야 <property name=""> 에서 ctrl+space 했을 때 자동완성 됨
* UserController, OrderController