Item32. Generic과 가변인수를 함께 쓸떄는 신중하라

가변인수에 Generic은 타입 안전하지 않다.

가변인수(varargs) method와 Generic은 JDK 5때 함께 추가되었다.

가변인수 method를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어진다.

가변인수 type을 실체화 불가 타입으로 선언하면 heap pollution 이 생길 수도 있다는 compile 경고가 뜬다.

아래와 같은 상황에서 heap pollution이 발생할수 있기 떄문이다.

Read more

Item31. 한정적 와일드카드를 사용해 API 유연성을 높이라

Generic 타입 불공변 특성으로 인한 제약

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
32
33
34
35
public class Stack<E> {

private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY =16;

public Stack(){
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}

public void push(E e){
ensureCapacity();
elements[size++] =e;
}

public E pop(){
if(size ==0 ){
throw new EmptyStackException();
}
E result = elements[--size];
elements[size] =null;
return result;
}

public boolean isEmpty(){
return size == 0;
}

private void ensureCapacity(){
if(elements.length == size){
elements = Arrays.copyOf(elements,2*size+1);
}
}
}

Generic type Stack에서 pushAll method를 추가한다고 가정하자

Read more

EntityManagerFactory ,EntityManager, Persistent Context 주요 개념

Jpa 의 EntityManagerFactory ,EntityManager, Persistent Context 주요 개념을 알아보기전에 spring boot에서 Jpa 환경을 setting 해주었다.

spring boot에서는 /meta-inf/persistence.xml JPA 설정파일을 인식하지 않고, 기본으로 설정해준다.

spring이 아닌 환경에서는 /META-INF/persistence.xml 파일을 설정해주어야 한다.

boot에서는 다음과 같이 EntityManagerFactory 와 EntityManager 를 주입받을 수 있다.

1
2
3
4
5
@PersistenceContext
EntityManager em;

@PersistenceUnit
EntityManagerFactory emf;
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
@SpringBootTest
class JpaApplicationTests {

@PersistenceUnit
EntityManagerFactory emf;

@Test
void basicJpa() {

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();

try{
transaction.begin(); // transaction 시작
// 비즈니스 로직
transaction.commit();
}catch (Exception e){
transaction.rollback();
}
finally {
em.close();
}
emf.close();
}
}

boot에서 자동으로 설정해준 Persistence class(Jpa 설정 정보)를 주입받아, EntityManagerFactory instance를 생성했다.

참고로 Jpa는 기본적으로 데이터 변경시 Transaction을 당연히 필요로 하며, transaction이 없는 경우는 예외를 던진다. (javax.persistence.TransactionRequiredException)

EntityManagerFactory

  • EntityManagerFactory 는 Persistence class로부터 Jpa를 동작시키기 위한 기반 객체를 만들고, Jpa 구현체에 따라서는 DB connection pool도 만든다

  • 객체 생성 비용이 매우 큼으로, application 전체에 딱 한번만 생성하고 공유된다 (singleton)

  • DB 1개당 하나의 EntityManagerFactory가 생성된다.

  • multi-thread 상황에서 공유 가능하다

EntityManager

다음으로 EntityManagerFactory에서 EntityManager를 생성하게 되는데,

EntityManager 가 사실상 Jpa 기능의 대부분을 제공한다.

  • 요청시(Thread별로)마다 EntityManagerFactory로부터 EntityManager가 생성된다. (Thread간에 공유하면 race condition 이 생길 수 있다. )

  • EntityManager는 내부적으로 DB connection을 가지고 DB와 통신하는데, DB 연결이 꼭 필요한 시점까지는 Connection을 가져오지 않는다.

Persistence Context (영속성 컨텍스트)

Entity를 영구 저장하는 환경으로, EntityManager가 생성될떄 하나 만들어지고, EntityManager는 이 영속성 컨텍스트에 Entity를 보관하고 관리한다.
Read more

Jpa

Jpa 란?

  • Java Persistence API (JPA)는 Java 진영의 ORM (Object relational mapping ) 기술 표준으로서 (API 표준 명세로 , JPA 자체가 구현체는 아니다. ) , JDBC API를 추상화해 application과 JDBC 사이에서 동작한다.

  • Jpa를 사용하려면 그 구현체를 선택해야하는데, 구현체는 hibernate , EclipseLink , DataNuclues가 존재하며 이중에서 hibernate가 가장 대중적이다.

  • ORM의 정의

    객체와 관계형 데이터베이스의 엔티티를 매핑한다
Read more

Java Virutal Machine - Memory,실행 엔진 내부 구성요소

JVM의 목표

Java 코드를 작성하고 compile하면 bytecode (.class) 가 생성된다. 이 bytecode를 실행해주는 역할이 Jvm의 역할이다. byte code는 최종적으로 machine code (native code)로 변경되서 실행되는데 이는 CPU에 종속적이다. Jvm은 OS별로 구현체가 여러개 있어, Java source 코드는 운영체제와는 독립적으로 작성될 수 있도록 해준다.

Jvm은 bytecode (.class)를 실행해주는데, 사실 Java 이외에도 .class file이 생성되는 타 프로그래밍 언어들을 실행할 수 있다 예를 들면 Kotlin ,Scala 가 있다.

Read more

Item30. raw type 보다는 Generic method로 만들어라

Generic Method

아래와 같이 raw type을 받는 method는 타입 안전하지 않다.

1
2
3
4
5
public static Set union(Set s1, Set s2){
Set result = new HashSet<>(s1);
result.addAll(s2);
return result;
}

아래와 같이 다른 타입의 Generic이 와도 어떠한 compile error도 발생하지 않고 runtime exception이 터진다.

1
2
3
Set<String> strings = Set.of("a", "b", "c");
Set<Integer> integers = Set.of(1, 2, 3);
Set<String> unionResult = union(strings, integers);

method parameter와 반환타입을 다음과 같이 Generic method로 변경함으로 타입 안전하게 만들 수 있다.

1
2
3
4
5
public static <E> Set<E> union(Set<E> s1,Set<E> s2){
Set<E> result = new HashSet<>(s1);
result.addAll(s2);
return result;
}
Read more

Spring validation - BindingResult

BindingResult

spring은 입력데이터에 대한 validation과 예외처리를 지원해준다. org.springframework.validation.BindingResult 가 validation 기능을 지원해주는 주요 객체 중 하나이다. BindingResult는 입력 form의 필드값 중에 오류가 있으면 오류정보를 담아둔다.

Read more

Item29. 이왕이면 Generic Type으로 만들어라

Generic Type 변환

Stack Generic Type으로 변경할 경우 , Client에서 Stack에서 꺼낸 객체를 형변환할 필요가 없으며 동시에 ClassCastException 이 나지 않는 장점을 갖는다.

Item 28 에서는 Generic 사용시 배열보다 리스트를 고려하라고 권고는 하였으나 Generic type 안에서 List를 사용하는게 항상 가능하지도 않고, Java가 기본 타입으로 List를 제공하지 않으므로 성능 향상 목적으로 기본 타입인 배열을 사용하기도 한다.

Read more

Item28. 배열보다는 리스트를 사용하라

배열과 Generic type의 차이점

  1. 배열은 공변(covariant) 인 반면 Generic은 불공변(invariant) 이다.

Sub class가 Super class의 하위 class라고 가정하면 배열 Sub[]는 Super[]의 하위 타입이 된다.
반면에 서로 다른 타입인 Type1과 Type2가 있을떄 Generic인 List<Type1> List<Type2> 은 아무 계층관계도 가지지 않는다.

1
2
3
4
5
6
7
// Array 
Object[] longs = new Long[1];
longs[0] = "타입이 다름에도 컴파일에러가 나지 않습니다."; //ArrayStoreException

// Generic
List<Object> ol = new ArrayList<Long>(); // compile Error

배열은 type으로 인해 runtime Exception이 발생할 수 있는 반면, generic인 compile 경고를 먼저 띄워준다.

  1. 배열은 실체화 된다.

배열은 runtime 에도 원소의 타입을 인지하고 확인한다, 예를 들면 Long 배열에 String을 넣으려고 하면 runtime에 이를 확인하고 예외를 발생시킨다.
반면 generic은 runtime에 타입을 소거한다 (type erasure). 원소의 타입을 compile time에만 검사하며 , runtime에는 모른다.

Read more

Servlet Filter 와 Spring Interceptor

Servlet Filter

  • servlet filter는 http 요청이 dispatcher servlet에 전달되기전에 호출되는 객체로서, 호출되는 순서는 아래와 같다.

HTTP message –> WAS –> Filter –> dispatcher servlet

  • dispatcher servlet: Tomcat과 같은 servlet container 안에 HTTP 요청을 가장 먼저 받아, 적합한 controller에게 요청을 forwarding 해주는 일종의 front controller
    (https://docs.spring.io/spring-framework/docs/3.0.0.M4/spring-framework-reference/html/ch15s02.html)

  • 주로 logging, encryption , input validation 과 같은 공통 관심사에 기능을 적용하고자 할떄 활용된다.

  • Filter chain : Filter는 chain 형태로 구성되어, 여러개의 필터를 끼울 수 있다.

Read more