Board  ALL

To-do
ref.] https://velog.io/@ahnick/Java-Call-by-Value-Call-by-Reference


Dev Jinwon's Share
f
t
To-do
ref.] https://jiwondev.tistory.com/154


Dev Jinwon's Share
f
t
To-do
ref.] https://velog.io/@pllap/Java%EC%97%90%EC%84%9C%EC%9D%98-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D


Dev Jinwon's Share
f
t
To-do


Dev Jinwon's Share
f
t
To-do


Dev Jinwon's Share
f
t
Spring Security Tag 속성

1. ifAllGranted : 나열한 모든 권한에 해당할 경우
2. ifAnyGranted : 나열한 권한 중 하나라도 해당될 경우
3. ifNotGranted : 나열된 권한 중 하나라도 해당할 경우, 내용을 보여주지 않는다.


Dev Jinwon's Share
f
t
JUnit



- 일괄, 동시 테스트 가능
- 메서드, 클래스, 패키지 단위로 각각 테스트를 한번에 수행할 수 있다.
- 그러나 순서를 보장하지 않는다.
- 하나의 테스트가 끝날 때마다 공용 저장 내용을 초기화해줘야 한다.

- TDD란?
- Test를 먼저 만들고 구현체를 나중에 만드는 방식(기존 방식과 반대)
- Test method는 한글, 한문으로도 직관적으로 생성 가능하다.
- Test 순서를 아래와 같이 하는 것을 권장
- given : test data를 의미
- when (or what): 테스트 로직
- then : 테스트 결과

- 테스트는 정상 flow보다 예외 flow가 더 중요!

- Servic Class의 junit Test Class를 바로 생성할 수 있다.
- 클래스 명에 커서를 위치시키고 단축키(ctrl + shift + t) 사용.
- Popup에서 Test Library는 jUnit5를 선택
- Popup에서 Test method를 선택


Dev Jinwon's Share
f
t
AOP : Aspect Oriented Programming 관점지향프로그래밍


- AOP가 필요한 필요한 상황
- 모든 메서드의 호출시간을 측정하고 싶다면
- 시간 측정 기능은 공통 로직. 공통관심사항.
- 핵심 비지니스 로직은 핵심 관심사항.
- 모든 메서드에 소스코드를 남길 것인가?
- 시간 측정 기능과 핵심 비즈니스 로직이 섞이면 유지보수가 어렵다
- 별도의 공통 로직으로 만들기가 어렵다
- 시간 측정 기능의 요구사항 변경시 모든 메서드를 찾아가면서 변경하기가.... 어렵다..
- AOP를 적용하면
- '원하는 곳'에 공통 관심 사항을 적용할 수 있다.
- 시간 측정 AOP 등록

- AOP class 생성
package net.linkednest.test.aop;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.springframework.stereotype.Component;

@Aspect

@Component

public class TimeTraceAop {

@Around("execution(* net.linkednest.test..*(..))")

public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {

long start = System.currentTimeMillis();

System.out.println("START : " + joinPoint.toString());

try {

return joinPoint.proceed();

} finally {

long finish = System.currentTimeMillis();

long timeMs = finish - start;

System.out.println("END : " + joinPoint.toString() + " " + timeMs + " ms");

}

}

}


- @Component어노테이션을 추가로 선언해서 사용할 수도 있고, SpringConfig에 SpringBean을 직접 등록해서 사용할 수도 있다.
- @Around("execution(* hello.hellospring..*(..))")
- Around 어노테이션은 AOP를 적용할 범위를 지정하는 것
- hello.helloworld 패키지 하위의 내용에 적용하겠다는 의미
- SpringBean으로 직접 등록하는 경우(선호)

- SpringConfig.java에서
@Bean

public TimeTraceAop timeTraceAop() {

return new TimeTraceAop();

}
- Console에서 결과확인
START : execution(String net.linkednest.test.controller.MemberController.list(Model))

START : execution(List net.linkednest.test.service.MemberService.findMembers())

START : execution(List org.springframework.data.jpa.repository.JpaRepository.findAll())

Hibernate: select member0_.id as id1_0_, member0_.name as name2_0_ from member member0_

END : execution(List org.springframework.data.jpa.repository.JpaRepository.findAll()) 173 ms

END : execution(List net.linkednest.test.service.MemberService.findMembers()) 181 ms

END : execution(String net.linkednest.test.controller.MemberController.list(Model)) 189 ms


- 장점
 - 핵심 관심사항과 공통 관심사항을 분리

- 핵심 관심사항을 유지 가능하게 됨

- (시간 측정 로직을) 별도의 공통 로직으로 생성

- (시간 측정 기능의) 변경 필요하면 이 AOP Class의 로직만 변경하면 됨.

- 원하는 적용 대상을 선택할 수 있다.

- 패키지 단위가 되겠지

- AOP 동작방식

- Proxy개념의 사용

- Spring Bean을 등록할 때 대상이 되는 진짜 Controller, Service 등이 아닌 가짜 Controller, Service 등을 앞에 세워두고 가짜 스프링빈이 끝나고 AOP에서 joinPoint.proceed()가 실행되면 진짜 Class를 호출해줌.

- AOP의 타겟이 전체 패키지 대상인 경우, proxy Controller -> real Controller -> proxy Service -> real Service -> proxy Repository -> real Repository 호출 순이 된다.

- DI의 적용으로 AOP 적용이 가능.


Dev Jinwon's Share
f
t
참고 : DI(Dependency Injection)



- DI의 세가지 방식

1. 필드 주입
@Autowired 

private MemberService memberService;
2. setter 주입
@Autowired

public void setMemberService(MemberRepository memberRepository) {

this.memberRepository = memberRepository;

}
3. 생성자 주입
@Autowired

public MemberService(MemberRepository memberRepository) {

this.memberRepository = memberRepository;

}
- 의존관계가 실행 중에 동적으로 변경되는 경우는 거의 없으므로, 생성자 주입을 권장.



Dev Jinwon's Share
f
t
Spring DB 접근 기술 - Spring Data JPA


- 개요
- JPA를 편하게 사용할 수 있도록 한번 더 감싼 기술
- JPA를 편리하게 사용하도록 도와주는 기술
- 인터페이스만으로 개발을 완료할 수 있다.
- 반복 개발해온 기본CRUD기능도 스프링 데이터JPA가 모두 제공
- JPA를 먼저 학습 후에 스프링 데이터 JPA를 보는 것이 더 좋다
- 개발자는 핵심 비즈니스 로직을 개발하는데 집중할 수 있다.
- 인터페이스의 생성
- 인터페이스가 인터페이스를 상속할 때는 extends 사용
- 스프링데이터 JPA가
- Repository 인터페이스에 대한 구현체를 스프링 데이터 JPA 내부적으로 만들어냄.
- 그리고 자동으로 스프링 빈에 등록시킴.
- 개발자가 등록할 필요가 없음.

- Code
 package net.linkednest.test.repository;

import net.linkednest.test.domain.Member;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {

@Override

Optional<Member> findByName(String name);

}

- 일반적인 기본 CRUD는 스프링데이터 JPA가 제공하지만 임의의 테이블의 특정 컬럼을 조건으로 조회를 하려고 하면 메서드를 추가를 해줘야 한다.
- 위 코드에서 findByName이 있고, 다른 메서드들이 override되지 않은 이유.
- 페이징 기능 자동 제공한다고.
- 실무에서는 JPA와 Spring Data JPA를 기본으로 사용하지만
- 복잡한 동적 쿼리는 queryDsl이라는 라이브러리를 사용해서 처리해야 할 수도.
- 쿼리도 Java Code로 안전하게 작성 가능
- 동적쿼리도 편리하게(?) 작성가능하다고.
- JPA/Spring Data JPA/queryDsl로 해결하기 어려운 쿼리는
- JPA가 제공하는 네이티브 쿼리를 사용하거나
- jdbcTemplate을 사용하면 된다고 한다.
- JPA와 마이바티스 혼용도 가능하다고 함!!!

- SpringBean

- Code
 package net.linkednest.test;

import net.linkednest.test.repository.*;

import net.linkednest.test.service.MemberService;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class SpringConfig {

private final MemberRepository memberRepository;

public SpringConfig(MemberRepository memberRepository) {

this.memberRepository = memberRepository;

}

/*private DataSource dataSource;

@Autowired

public SpringConfig(DataSource dataSource) {

this.dataSource = dataSource;

}*/

/*private EntityManager em;

@Autowired

public SpringConfig(EntityManager em) {

this.em = em;

}*/

@Bean

public MemberService memberService() {

// return new MemberService(memberRepository());

return new MemberService(memberRepository);

}

/* @Bean

public MemberRepository memberRepository() {

return new JpaMemberRepository(em);

// return new JdbcTemplateMemberRepository(dataSource);

// return new JdbcMemberRepository(dataSource);

// return new MemoryMemberRepository();

}*/

}



Dev Jinwon's Share
f
t