Presentation is loading. Please wait.

Presentation is loading. Please wait.

SpringFramework 중간고사 요약 REST by SpringFramework.

Similar presentations


Presentation on theme: "SpringFramework 중간고사 요약 REST by SpringFramework."— Presentation transcript:

1 SpringFramework 중간고사 요약 REST by SpringFramework

2 인터페이스란? 인터페이스란 인터페이스는 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상 매서드를 갖지만 추상화 정도가 높아서 몸통을 갖춘 일반 매서드 또는 맴버변수를 구성원으로 가질 수 는 없다. 기본 설계도와 같다. [인터페이스의 작성] Interface 인터페이스 이름 { public static final 타입 상수이름 = 값; public abstract 매서드이름(매개변수목록); } 1.8부터 (static 매서드와 디폴트 매서드도 허용됨) [인터페이스의 상속] 인터페이스는 인터페이스로만 상속받을 수 있으며, 클래스와 달리 다중상속이 가능 Ex) interface Fightable extends Movable, Attackable{ ~~~ }

3 인터페이스란? [인터페이스의 구현] 자체적으로 인스턴스를 생성할 수 없으며, 몸통을 만들어주는 클래스를 작성해야함
Ex) Class 클래스 이름 implements 인터페이스이름 [인터페이스를 이용한 다형성] - 인터페이스 Fightable를 클래스 Fighter가 구현했을 때 인스턴스를 클래스의 참조변수로 참조가능 ex) Fightable f = (Fightable) new fighter(); Fightable f = (Fightable) new fighter(); - 인터페이스는 메서드의 매개변수의 타입으로 사용 가능 (호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야함) ex) void attack(Fightable f) //interface Fightable - 매서드의 리턴타입으로 인터페이스 타입 지정도 가능

4 인터페이스란? [인터페이스의 구현] 자체적으로 인스턴스를 생성할 수 없으며, 몸통을 만들어주는 클래스를 작성해야함
Ex) Class 클래스 이름 implements 인터페이스이름 [인터페이스의 장점] - 개발 시간을 단축시킬 수 있다 (인터페이스를 제공함으로서 양쪽이 동시에 개발 진행이 가능함) - 표준화가 가능하다 (프로젝트의 기본틀을 인터페이스로 작성하여 제공함으로써 정형화된 프로그램 개발가능) 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다 (상속 관계에 있지 않고 같은 조상클래스가 있지 않아도 하나의 인터페이스를 공통으로 구현하여 관계를 맺어줄 수 있다.) 독립적인 프로그래밍이 가능하다 (선언과 구현을 분리시켜 실제 구현에 독립적인 프로그램을 작성하는 것이 가능)

5 다수의 데이터를 다루고 표현하기 위한 표준화된 프로그래밍을 뜻함
컬렉션 프레임워크 LIST 다수의 데이터를 다루고 표현하기 위한 표준화된 프로그래밍을 뜻함 List, Set , Map Collection Map List Set 인터페이스 특징 List 순서가 있는 데이터의 집합, 데이터 중복 허용 (예) 대기자 명단 구현클래스 : ArrayList, LinkedList, Stack, Vector Set 순서를 유지하지 않는 데이터의 집합, 데이터의 중복을 허용하지 않는다. 예) 양의 정수의 집합, 소수의 집합 구현클래스 : HashSet, TreeSet 등 Map 키(Key)와 값(Value)의 쌍으로 이루어진 데이터의 집합 순서는 유지되지 않으며, 키는 중복을 허용하지 않고, 값은 중복을 허용한다. (예) 우편번호, 지역번호(전화번호) 구현클래스 : HashMap, TreeMap, Hashtable, Properties

6 JDK 1.5 버전의 혁신적인 도입 GENERICS
1. 타입 안정성을 제공 - 의도하지 않은 타입의 객체가 저장되는 것을 막고, 저장된 객체를 꺼내올 때 잘못 형변환 되는 것을 줄여줌 2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해짐 [클래스 정의] [Generics 표현] Class Box{ Object item; Void setItem(Object item) { this.item=item; } Object getItem() { return item; Class Box<T>{ T item; Void setItem(T item) { this.item=item; } T getItem() { return item; //Type Variable

7 Generics란 무엇인가? GENERIC는 선언 시에 <T>로 선언한 다음
[객체 생성시] Class Box<T>{ T item; Void setItem(T item) { this.item=item; } T getItem() { return item; //Type Variable //T 대신 String 지정O Box<String> b = new Box<String>(); b.setItem(new Object()); b.setItem(“ABC”); String item = (String) b.getItem(); //에러. String 외 지정X //String 값이므로 O //형변환 할 필요가 없음 static 맴버에는 타입 변수 T 사용이 안됨 (모든 객체에 대해 동일하게 동작해야 하기 때문) Generic 타입의 배열을 생성하는 것도 안됨 (new T[10] 이런 방식은 안됨)

8 클래스 내에 선언된 클래스(긴밀한 관계의 두 클래스)
내부 클래스 내부 클래스의 이해 클래스 내에 선언된 클래스(긴밀한 관계의 두 클래스) - 내부 클래스에서 외부 클래스의 맴버들을 쉽게 접근할 수 있다 - 코드의 복잡성을 줄일 수 있다. 내부 클래스 특 징 인스턴스 클래스 외부 클래스의 맴버 변수 선언 위치에 선언 하며, 외부 클래스의 인스턴스 맴버처럼 다뤄진다. 주로 외부 클래스의 인스턴스 맴버들과관련된 작업에 사용될 목적으로 선언된다 스태틱 클래스 외부 클래스의 맴버변수 선언 위치에 선언하며, 외부 클래스의 static맴버처럼 다뤄진다. 주로 외부 클래스의 static 맴버, 특히 static 매서드에서 사용될 목적으로 선언된다. 지역 클래스 외부 클래스의 매서드나 초기화 블록 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다. 익명클래스 클래스 선언과 객체의 생성을 동시에 하는 이름 없는 클래스

9 Lamda 이해하기 Lamda 새로운 프로그래밍 스타일과 전략을 짤 수 있는 기능입니다.
(Java 8 부터 지원이 가능했지만 이미 모든 프로그래밍 언어에 있던 식) - 람다는 간결하게 표현된 단일 메소드를 말하며, 어떤 행동을 정의함 - 문법 (예시) (Long val1, String val2 ) -> val1 + val2.length() 왼쪽은 매서드 인수 오른쪽은 해야할일(비즈니스 로직, 실제 함수 본체) 이름 없는 익명 함수를 의미한다. 입력할 인자 값 결과값

10 Lamda 이해하기 [Lamda 활용의 예시] Lamda 활용법 매서드 람다식 int max(int a, int b){
return a>b? a : b; } (int a, int b) ->{ return a > b? a : b;} (int a, int b) -> a > b? a : b ( a, b) -> a > b? a : b int printVal(String name, int I){ System.out.println(name+"="+i); (String name, int i) ->{System.out.println(name+"="+i);} (name,i) -> {System.out.println(name+"="+i);} (name,i) -> System.out.println(name+"="+i) int square( int x){ return x*x; (int x) -> x * x (x) -> x * x x -> x * x int roll(){ return (int)(Math.random() * 6); ()-> {return (int)(Math.random() * 6); } ()-> (int)(Math.random() * 6)

11 MVC 모델이란 디자인 패턴 중에 하나인 MVC 모델은
Model – View – Controller 로 구분하여 설계하는 방법을 뜻함 View [View] 고객이 원하는 결과를 보여줌 DB Model Controller [Controller] - 고객의 요청이 들어옴 - 고객의 요청을 기반으로 view나 model에게 요청을 보낸다 - 비즈니스 로직이 배치되어 있음 [Model] - DB의 데이터를 모델링함 - DB 데이터를 Controller에 전송한다 MVC 모델은 각 분야의 담당자들이 협업이 가능하며 단위테스트가 가능할 수 있도록 구성된 모델이다

12 REST API의 이해 Representational safe transfer (REST) 기본요소
웹의 장점을 최대한 활용할 수 있는 네트워크 기반의 아키텍쳐 REST는 기본적으로 CRUD(생성/조회/수정/삭제) 4가지 메서드만으로 표현하며, 고객관리 프로그램에서는 다음과 같이 진행한다 Resource Method Message 기본요소 - 이름이 minio인 사람을 생성한다 REST 매서드 종류 기능 POST 생성 GET 조회 PUT 수정 DELETE 삭제 [REST 표현시] HTTP POST, { “users”:{ “name”:”minio” } 매서드 : HTTP POST 리소스 : 메시지 : JSON 형식의 {~~~}

13 TDD는 기능코드를 짜면서 테스트 코드를 같이 짜는 방법입니다.
테스트 주도 개발 (Test Driven Development) MVC의 디자인 철학 중 하나가 테스트 용이성(쉬운 테스트)!!! 이를 실현한 것이 바로 TDD 방식입니다 테스트 주도 개발(TDD)는 철학입니다 단위테스트 X 기능 코드 버그수정 코드를 작성하는 시간은 줄어듬 전체적으로 더 많은 버그 발생 기능 코드 우선 방식 기능 코드 버그 수정 버그를 수정하는데 필요한 시간은 줄어듦 전체적으로 동일한 시간 필요 단위테스트 테스트 우선 방식 기능 코드 버그 수정 디버깅 시간이 줄어들어 효과적이다. 단위테스트 유리 단위테스트 시간의 문제도 있지만 실수할 확률이 적어지고 옥상으로 끌려갈 상황이 덜 발생하는 방법론입니다. TDD는 기능코드를 짜면서 테스트 코드를 같이 짜는 방법입니다.

14 JUnit 은 Java의 단위테스트 Framework
문자 혹은 GUI 기반으로 실행됨 단정문으로 테스트 케이스의 수행 결과를 판별함 (assertEquals(예상 값, 실제 값)) 어노테이션으로 간결하게 지원함 결과는 성공(녹색), 실패(붉은색) 중 하나로 표시

15 JUnit 은 다음 단정문으로 주로 테스트를 합니다. 저 신호등을 통과하지 못하면 빨간불이 켜집니다!
의미 assertArrayEqual(a,b) 배열 a,b가 일치함을 확인 assertEqual(a,b) 객체 a,b의 값이 같은 지 확인 assertSame(a,b) 객체 a,b가 같은 지 확인 assertTrue(a) A가 참인지 확인 assertNotNull(a) A가 null이 아님을 확인 [모든 단정문의 기능] 단정문은 신호등이라고 생각하면 됩니다. 저 신호등을 통과하지 못하면 빨간불이 켜집니다!

16 이러한 구조를 위해서 pom.xml에 다음과 같이 정의되어있어야함
JUNIT 지원구조 [스프링에서의 JUnit 지원 구조] 스프링은 프로젝트 생성시 기본적으로 아래 위치에 자동으로 JUnit 테스트를 위한 장소가 마련되어져 있음 테스트가 시작되면 DemoApplicationTest.java는 DemoAppiivation.java인척 행세하면서 테스트를 진행하게 됩니다(가짜 파일임) 이러한 구조를 위해서 pom.xml에 다음과 같이 정의되어있어야함 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>

17 JDBC란? JDBC는 데이터 액세스 언어인 SQL을 바탕으로 만들어짐. 비록 비생산적인 코드와 반복적인 코드로 효율성이 떨어져 myBatis,JPA,하이버네이트 등의 퍼시스턴스기술이 대체되고 있지만 낮은 수준의 데이터 조율이 가능하다는 점에서 여전히 쓰여지고 있다. [App.java.에서 플레이스 홀더 :a :b 사용하기] 플레이스 홀더 :a , :b는 C언어의 printf의 %d와 비슷한 느낌입니다 addValue 를 통해서 추가가 가능합니다

18 JPA란? [JPA 특징] - 자바 객체와 데이터베이스에 저장된 데이터를 매핑하는 기능
JPA는 Java Pesistence API의 약자 자바 표준인 O/R 매퍼(Object/Relational Mapper)에 관련된 명세임. 하이버네트나 이클립스 링크 같은 라이브러리를 사용하여 구현함 [JPA 특징] - 자바 객체와 데이터베이스에 저장된 데이터를 매핑하는 기능 - 데이터베이스에서 실행할 CRUD 처리를 캡슐화한 API - 자바 객체를 검색하는 데 사용하는 쿼리 언어인 JPQL - 다양한 데이터베이스에 존재하는 차이점을 JPA가 흡수함

19 JPA 적용코드 JPA활용하기 [Customer.java] [Customer.java]
기본적으로 findOne, save, findAll, delete 매소드가 제공됨 새로운 기능을 정의할때도 @Query를 활용해서 정의하면 됨

20 빈을 담는 그릇 컨테이너 컨테이너란 컨테이너 안에는 많은 객체가 있고 컨테이너는 이 객체를 생성부터 소멸까지 관리를 해줌
Bean을 담는 그릇 빈팩토리, 애플리케이션 컨텍스트 여기서 객체가 생성, 소멸, 주입됨 컨테이너 안에는 많은 객체가 있고 컨테이너는 이 객체를 생성부터 소멸까지 관리를 해줌 코드는 내가 짰지만 객체의 생성과 소멸은 컨테이너에서 알아서 함 빈을 인스턴스화 -> xml/config 파일 읽고 값을 주입 -> ….-> 인스턴스폐기 (그냥 그런가보다 하고 신경 안쓰고 프로그램을 짜면 됩니다만 만약 누군가 짜놓은 시스템이 신경쓰여서 직접 한번 컨테이너를 만들어보면 이게 얼마나 어마어마한 작업인지 알게 될 거도 대신 해주는 스프링한테 고마워할 스프링 컨테이너는 크게 빈팩토리 / 애플리케이션 컨텍스트로 구분됨 빈팩토리는 너무 기능이 없어서 주로 applicationContext를 사용합니다.

21 컨테이너 - 인스턴스의 스코프(범위)를 제어할 수 있습니다.
이번 주에는 DI 컨테이너를 활용한 DI 예제입니다 DI 컨테이너를 통해 인스턴스를 생성하면 다음과 같은 이점이 있습니다 - 인스턴스의 스코프(범위)를 제어할 수 있습니다. (인스턴스를 싱글톤(계속 생존) 으로 할 건지 매번 새로 생성할지에 대한 사항) - 인스턴스의 라이프 사이클(생명주기)을 이벤트로 제어할 수 있다. (예를 들면, 인스턴스를 생성할 때와 인스턴스를 소멸할 때 이벤트처리) - 공통 처리를 포함할 수 있다 (예를 들면, 트랜잭션 관리나 로깅관리) - 객체 사이의 의존 관계가 느슨해집니다

22 DI(의존성 주입) 의 이해 아주 단순한 구조의 계산 프로그램 Entry Point AddCalCulator
(DiTestApplication) AddCalCulator

23 DI(의존성 주입) 의 이해 이번엔 뺄셈을 추가해보겠습니다 Entry Point AddCalCulator
(DiTestApplication) AddCalCulator SubCalCulator 이번엔 곱셈을 추가해볼까요?

24 DI(의존성 주입) 의 이해 이번엔 뺄셈을 추가해보겠습니다 Entry Point AddCalCulator
(DiTestApplication) AddCalCulator SubCalCulator 이번엔 곱셈을 추가해볼까요?

25 DI(의존성 주입) 의 이해 이번엔 곱셈을 추가해보겠습니다 Entry Point (DiTestApplication)
AddCalCulator SubCalCulator MulCalCulator 뭐가 귀찮은지 더 안해봐도 알겠죠?

26 인터페이스 Calculator 추가(com.example.app)
DI(의존성 주입) 의 이해 추상화를 한번 해보겠습니다 인터페이스 Calculator 추가(com.example.app) Entry Point (DiTestApplication) CalCulator SubCalculator MulCalculator AddCalculator 나머지 Sub/MulCalculator에도 Implements Calculator를 써줍니다

27 이후 예제에선 뺄셈, 곱셈은 신경안쓰고 Add만 가지고 하고
DI(의존성 주입) 의 이해 추상화된 상태에서 DI 컨테이너를 활용 DI Container Entry Point (DiTestApplication) CalCulator SubCalculator MulCalculator AddCalculator 이후 예제에선 뺄셈, 곱셈은 신경안쓰고 Add만 가지고 하고 최종 변화 후 뺄셈,곱셈을 적용하겠습니다.

28 DI(의존성 주입) 의 이해 [Caculator 인터페이스] [AppConfig 클래스] [AddCalculator 클래스]
[DiTestApplication 클래스]

29 DI(의존성 주입) 의 이해 작성한 프로그램의 특징(장/단점)
1. DiTestApplication에서 AddCalculator를 완전히 숨김 (AppConfig.java 안보면 절대 모름) 2. DI 컨테이너에서 getBean을 통해 bean을 가져왔지만 DI는 아님 (여전히 호출 방식임, 호출이 늘어나면 날수록 getBean은 점점 많이질 것임) Calculator calculator = new AddCalculator()가 Calculator calculator = context.getBean(Calculator.class)로 된거지 여전히 똑같은 호출 방식임 이 상태로 프로그램이 커지면 커질수록 모듈은 복잡해지고 코드는 지저분해짐 이를 해결하는 것이 바로 DI입니다.

30 DI(의존성 주입) 의 이해 프로그램 변경 계획 사실 DiTestApplication이 생각보다 복잡해졌습니다.
그래서 Frontend 클래스를 생성해서 DiTestApplication의 역할을 줄여줘보려고 합니다 활용한 DI를 구현하고자 합니다

31 DI(의존성 주입) 의 이해 [Frontend 클래스(추가) com.example.app] [AppConfig 클래스]
오토와이어링 구현 추가되는 부분 [DiTestApplication 클래스]

32 DI(의존성 주입) 의 이해 작성한 프로그램의 특징
Frontend에 getBean(Calculator.class) 가 바뀜 하지만 여전히 불만스러운 점이 2가지가 있습니다. 똑같은 코드만 붙여넣는 AppConfig.java가 필요한가!! 왜 굳이 Frontend 파일을 앞으로 따로 빼놓았는가!! 먼저 1번 문제를 해결하기 위한 방법이 입니다

33 DI(의존성 주입) 의 이해 @ComponentScan은 @Component를 붙인 클래스 들을 별도의 AppConfig 없이
자동으로 검색해서 연결해주는 애너테이션입니다. 실습 예제는 간단합니다. 연결하고 싶은 클래스(인터페이스 붙이고 붙이면 됩니다. @Component 추가 클래스 : AddCalculator 클래스 , Frontend 클래스 @ComponentScan 추가 클래스 : DiTestApppication 클래스 [추가예시] @ComponentScan은 본인의 패키지를 포함한 하위 패키지의 아래와 같은 애너테이션을 검색하여 등록합니다. 이제 AppConfig.java 파일을 지워주세요. 실행해보면 기능을 수행할 겁니다

34 DI(의존성 주입) 의 이해 CommandLineRunner는 엔트리포인트(DiTestApplication)에서
일을 해야하는데 main이 가진 성격(static) 때문에 제한되는 행동을 따로 뺄 수 있는 기능입니다 [DitestApplication.java] 이제 Frontend.java 파일을 지워주세요. 실행해보면 기능을 수행할 겁니다.^^

35 AOP의 개념 개념 이해 애스펙트의 주목적은 횡단 관심사의 모듈화에 있다, 횡단 관심사란 한마디로 한 어플리케이션의 여러 부분에 영향을 주는 기능이다. 일례로 보안은 하나의 어플리케이션 내에서도 여러 객체 메소드의 보안 규칙에 영향을 미치는 횡단 관심사이다. 보안 트랜잭션 기타 Service A Service B Service C [AOP의 적용 대상]

36 AOP의 구성요소 검침원이야기 [검침원 이야기 ] 전력회사 검침원이 주택을 방문해서 전력량계를 읽어서 전력회사에 보고하고자한다. 검침원이 해야하는 일을 어드바이스라고 한다. 검침원은 전력을 제공받는 모든 주택이 방문대상이 된다. 이 방문대상을 조인포인트라고 한다. 하지만 검침원 한 명이 전력회사가 서비스하는 모든 주택을 다 돌아다닐 순 없다 자신이 맡은 지역에 주택만을 방문하게 된다. 검침원에게 방문 대상을 할당하는 것, 즉 각 검침원마다 어디를 방문대상으로 할 지를 포인트커트라고 한다. 어드바이스 - ‘무엇’을 ‘언제’ 할지 정의 포인트커트 - 작동조건 ‘어디서’ - 어드바이스가 어떤 조인포인트에서 적용되는지 조인포인트 - 어드바이스를 적용할 수 있는 곳을 ‘조인포인트’ , 방문대상 애스펙트 - 어드바이스와 포인트커트를 합친것

37 정보처리기능사 1 START i : 1씩 증가되는 숫자가 저장될 변수 J : i 값이 저장될 변수
수열 이용하기 START i : 1씩 증가되는 숫자가 저장될 변수 J : i 값이 저장될 변수 SW : + 와 – 중 어떤 연산자를 사용할 지 판단하는 변수 i = 0 J = 0 SW=0 i=i+1 yes no SW=0 SW를 활용하여 + - 를 교차하는 방법이며, P = -1 / P = P * -1 / SUM = SUM + i * P 와 같이 SW를 사용하지 않고 +, - 를 교차로 사용하는 방법도 있음 J=J+i J=J-i SW=1 SW=0 i<100 J START

38 정보처리기능사 2 A(16) : 0~9, A~F까지 저장되어 있는 1차원 배열
임의의 진법변환 START A(16) A(16) : 0~9, A~F까지 저장되어 있는 1차원 배열 B : 변환할 진수의 베이스, 2진법이면 B=2, 16진법이면 B=16 C : 10진수가 저장될 변수 D : C에 가장 가까운 B 의 누승이 저장될 변수 E : C를 D로 나눈 몫이 저장될 변수 F : C를 D로 나눈 나머지가 저장될 변수 READ B,C yes D<=C D=D*B no no D>1 yes D = D/B E = INT(C/D) F = C –E *D A(E+1) F = C –E*D 로 나머지를 구할 수도 있지만 F = MOD(C,D)로 구해도 된다 A[E+1]을 출력하는 것은 A[0]~ A[15]까지 있기 때문 D<>1 C = F STOP

39 정보처리기능사 3 DATA(10) : 정렬할 숫자가 저장될 배열 N : 입력받은 숫자의 개수가 저장될 변수
버블정렬 START DATA(10) N = 0 DATA(10) : 정렬할 숫자가 저장될 배열 N : 입력받은 숫자의 개수가 저장될 변수 I : 정렬 회전 수를 지정할 변수 J : 각 회전에서 비교횟수 및 배열의 위치를 지정할 변수 K : 두 값을 교환할 때 사용할 임시변수 N = N + 1 READ DATA(N) yes N<10 no 반복 i= 1,9,1 반복 j=1 ,10-i, 1 I와 J의 역할을 이해해야하며 데이터 교체가 언제 일어나며 누구와 교체되는 지 확인해야함 또한 반복문을 일반 분기문으로 변경했을때 (반복 네모를 마름모로 변경해서 풀어 표현하는 방법) 혼동하지 말고 풀 수 있어야 함 DATA(J)< DATA(J+1) no yes K=DATA(J) DATA(J) = DATA(J+1) DATA(J+1)=K DATA STOP

40 애네테이션(@)이란 애너터이션의 이해 전통적으로 자바 소스 안에 주석 중에 중요한 정보를 @로 표시하던 것에서 비롯됨
프로그램 자체에는 영향을 주지 않지만 컴파일러에게 정보를 제공한다고 생각하면 됨 애너테이션 의미 @Override 컴파일러에게 오버라이딩하는 메서드라는 것을 알린다 @Deprecated 앞으로 사용하지 않을 것을 권장하는 대상에 붙임 @SuppressWarnings 컴파일러의 특정 경고메시지가 나타나지 않게 해준다 @SafeVarargs 제너릭스 타입의 가변인자에 사용됨(JDK 1.7) @FunctionalInterface 함수형 인터페이스임을 알림(JDK 1.8) @Documented 애너테이션 정보가 javadoc으로 작성된 문서에 포함됨 @Retention 애너테이션이 유지되는 범위를 지정하는데 사용 @Repeatable 애너테이션이 반복해서 적용할 수 있게 한다(JDK 1.8) 명시적인 기능을 위해서 사용하는 경우도 있으며, 굳이 애너테이션을 쓰지 않고 기능을 구현할 수도 있음.

41 시험 잘봐요~~~


Download ppt "SpringFramework 중간고사 요약 REST by SpringFramework."

Similar presentations


Ads by Google