-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Hyunjun Jeong edited this page Mar 1, 2023
·
8 revisions
- A가 B라는 빈을 주입 받고 싶을 때 A도 빈으로 등록되어 있어야 하지만, A가 특정 상황으로 인해 빈으로 등록할 수 없을 때 getBean()으로 B를 조회할 수 있다
- 여기서 말하는 인터페이스는 자바의 인터페이스를 뜻하는 것이 아니다
- 빈은 꼭 인터페이스로 받아야할까?
- Serivce의 인터페이스가 없이 Service 클래스를 직접 주입받는다면 차라리 new로 생성하라고 할 만큼 의미 없다
- 생성자 주입 방식이 왜 좋냐??
- 수정자 주입은 자바 빈의 특성 떔에 잠깐 나왔던 사용법인 것 같다? 생성자 주입을 쓰라고 한다
- 생성자 주입의 문제는 주입을 여러 개 받을 때 동일한 타입을 받는 상황이라면 순서가 뒤바뀌어도 문제를 알아차릴 수 없다
- 롬복의 생성자 어노테이션의 문제점과 관련있음
- 생성자 주입에서 동일한 타입을 받을 때의 문제점을 해결하기 위한 전략도 있다고 한다
- 객체의 생명주기
- 스프링이 추상 클래스를 상속받아 빈으로 등록해준다는데?? 🚩
- 프로토타입 빈 (잘 안쓴다)
- XML로 설정하는 것은 혁신적인 기술이었다
- 여러 명이 동시에 개발한다면 같은 설정 파일을 수정하는 상황이 문제다
- 타입체크를 런타임시에 하기 때문에 띄워봐야 안다는 부분은 요즘 ide가 해결해준다
- 어노테이션은 자바보다 스프링이 먼저 나왔다
- 엔티티의 의존정보는 어노테이션으로 DB 매핑 정보는 xml로 할려고 했다는 것이 JPA의 초기 컨셉
- xml은 다 버리고
@Configuration
- 코드 레벨에서 의존관계가 있는 것과 런타임시에 의존관계가 만들어지는 것은 차이가 있다 📌
블랙박스 테스트, 화이트박스 테스트
2장 테스트 (모임 중 든 생각, 기억에 남는 말말말)
2장 읽기모임 정리
- 테스트 결과는 항상 일관성 있어야 한다.
- 개인적으로 테스트 상황을 재현하는게 힘들다. 그리고 트랜잭션도 설정해보질 않아서 추후에 배우게 될 것 같은데 기대된다.
- 엣날 JUnit의 테스트 메소드는 왜 public이어야 할까요?
-
johngrib
테스트 코드와 반증가능성에 대한 메모 (개인적으로 추천) - 토비님 왈 "테스트 코드를 돌리면서 왜 멍때리냐 개발을 계속 진행하라고 화낸적이 있다"
- 학습 테스트 , 버그 테스트 , 포괄적인 테스트
- 성의 없이 테스트를 만들어 문제가 있는 코드인데도 테스트가 성공하는 테스트코드가 제일 위험하다.
-
JUnit으로 테스트 코드를 작성하는 것과 TDD로 개발하는 것의 차이
- JUnit으로 테스트 코드를 작성하는건 개발한 코드를 검증하는 느낌
- TDD로 개발하는 것은 테스트 코드를 통과하기 위한 개발을 하는 느낌
-
스텁 , 목 , 더미 , 스파이 , 페이크 . 테스트 더블 ,테스트 대역 , Stunt double , 임포스터
- 아는 건 굵은 글씨 밖에...
- 테스트 코드를 작성하면서 비즈니스 로직이 추가 될 떄
- 문제가 있는 상황이 확실하다
- AWS를 모킹하는 경우도 있네
- 목을 걸 지점을 잘 지정하자
- 모킹도 복잡한 과정을 거치기 때문에 시간이 오래 걸린다
- 빠른 줄 알았는데 처음 알았다 그럼 테스트 상황 재현, 테스트 대상 집중을 위한 것 같다
- 테스트는 독립적이고 격리되어야 한다.
- private도 테스트 코드를 만들고 싶으면 만들어라. private도 테스트 가능하게 지원하는 기능이 있다
- 균등 분할
오라클 자바 튜토리얼
When to Use Nested Classes, Local Classes, Anonymous Classes, and Lambda Expressions
- 전략 패턴을 구성하는 것
- 템플릿 콜백 패턴은 전략 패턴의 한 가지이다.
-
Marker Interface
- 종립님이 단순 테스트를 위한 클래스에 마킹용으로 사용하신다고 했었던 것 같다.
- 이펙티브 자바에도 나온다고 한다.
- "람다식을 받도록 구현해보는 가장 쉬운 방법은 retry 를 구현해보면 돼요"
- 트랜잭션의 경계가 어디여야 하는가?? 이번 5장의 핵심이다
- 특별한 예외상황을 테스트 할 때 테스트하려는 서비스 클래스를 상속받아 테스트 하는 방법이 신박했다
-
mock
과 관련있다
-
- 옛날에는
PreparedStatement
,ResultSet
등등을 Service계층에서 사용하기도 했다고 한다 TransactionSynchronizationManager
- mock 라이브러리는 모킹할 때만 쓰는것이 아니다 stub이나 spy도 지원해준다
- mocking,stub,spy의 의미를 구분 잘 해서 말해야한다
- 6장은 프록시 팩토리 빈 까지는 읽기를 권장한다
- 리플렉션은 메타프로그래밍을 하기위한 방법으로 나왔다
- 메타프로그래밍 : 프로그래밍하면서 작성되었던 코드를 데이터로 취급할 수 있다
- 리플렉션 패키지는 tool을 사용할 떄 많이 사용했다
-
CGLIB
는 코드 제네레이션 라이브러리이다- 인터페이스를 구현하지 않은 클래스에 대해 프록시를 만들어야 할 떄
- (JDK에서는 불가하기 때문에) CGLIB는 상속을 통해 프록시를 만드는 기법을 사용한다
- 오버라이드 할 수 있는 모든 메소드를 프록시로 만든다
- 스프링에서는 두 가지 다 쓰인다
-
상속을 통해 프록시를 만들면 단점이 있다
-
final
클래스로 만들 수 없다 - 기본 생성자가 두 번 호출되는 점, 자바5부터 없어졌다
-
- 인스턴스를 만들 때 생성자를 호출하지 않고 만드는 트릭을 쓰는 라이브러리가 등장했다
- 프록시의 의미를 잘 이해해야 한다
- 프록시 패턴의 프록시
- 일반적으로 말하는 프록시
- Q : 다이나믹 프록시를 생성할 때 애플리케이션 클래스로더를 넘기게 되는데, 이 클래스 로더로 무슨 일이 일어나는지?
- A : 다이나믹 프록시는 새로운 클래스를 런타임에 동적으로 생성하여 만들고 연결 시키기 위해 클래스 로더를 필요로 한다.
- JPA에서는 프록시를 어떻게 사용하는지
-
@Entity
가 대표적이다 - 인터페이스가 있다면 CGLIB을 사용하지 않지만 인터페이스가 없다면 CGLIB을 사용한다
-
- 스프링 6
- 그랄VM
- 네이티브 컴파일
- 스프링에서 CGLIB을 없애야 된다. (충돌이 많이 나서)
- AspectJ
- AOP를 가장 깊이 있게 만들어낸 라이브러리
- @AspectJ 기반 AOP with Spring
- 코드위빙?
- JSON을 인코딩하고 디코딩하는게 CPU를 제일 많이 먹는다
-
Mock
도 성능에 큰 문제를 준다
AspectJ 책을 살펴보니 AOP 적용 예로 나오는게
Transaction, Security, Auditing, PerformanceMonitor 같은 것들이네요.
이게 가장 범용적인 듯하고, 그 이상은 애플리케이션 도메인에 특화된 필요에 따라 만들어질 것 같네요.
- 스프링부트에서는 java 아래 소스 코드는 컴파일 되어서 .class 파일이 되고 그거랑 resources 아래 있는 파일이랑 합쳐서 클래스 패스로 잡히게 된다.
- resources폴더 안에 작성하지 않고 다른 곳에 작성한다면 다 무시한다.
- 부트에서 하셨으면 자바 폴더와 리소스 폴더가 구분이 되어서 들어가야 한다. 소스 폴더에 넣은 일반 파일은 클래스패스로 잡히지 않는다.
- 토비님은 너무 복잡하거나 어려우면(돈과 관련되어있다면 무조건) TDD로 진행한다고 하신다. 그리고 TDD로 하지 않았다면 테스트 코드를 최대한 빠른 시간안에 작성하려고 하신다
- 기존에는
XmlSqlService
생성자에서 XML 언마샬링작업을 했다 - XML에서 SQL 정보를 읽어오는 책임과 SQL들을 매핑하는 책임에 맞는 개별의 인터페이스를 추가했다
-
SqlRegistry
,SqlReader
-
- 위 두 개의 인터페이스를
XmlSqlService
한 클래스에서 모두 구현하여 자기 참조를 하도록 리팩토링했다 -
자기 참조로 되어있는 각 책임들을 분리하기 위하여 구현 클래스들을 추가했다
-
SqlRegistry
를 구현하는HashMapSqlRegistry
추가 -
SqlReader
를 구현하는JaxbXmlSqlReader
추가
-
- 위의 구현체들을 DI하도록 디폴트 의존관계를 갖는
DefaultSqlService
를 추가 - 지금은 XML 정보를 읽어들이는
JAXB
로 구체적인 기술과 API에 종속되어 있기 때문에 서비스 추상화 적용- Spring의
Jaxb2Marshaller
테스트
- Spring의
-
BaseSqlService
와OxmSqlService
의 중복되는 메소드를 제거하기 위해 해당 메소드들은BaseSqlService
에게 실행하도록 위임했다 -
SQL을 조작하는 책임을 가진
UpdatableSqlRegistry
인터페이스를 구현하는-
ConcurrentHashMapSqlRegistry
클래스를 추가하였다 -
EmbeddedDbSqlRegistry
클래스를 추가하였다- 내장형 디비는 H2를 사용,
update(Map<String, String> sqlmap)
에 트랜잭션을 적용하였다
- 내장형 디비는 H2를 사용,
-
public class EmbeddedDbSqlRegistry implements UpdatableSqlRegistry {
JdbcTemplate jdbc;
TransactionTemplate template;
public void setDataSource(DataSource dataSource) {
jdbc = new JdbcTemplate(dataSource);
// DataSource로 TransactionManager를 만들고 이를 이용해 TransactionTemplate을 생성한다.
template = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
}
...
}
dataSource로 JdbcTemplate
을 생성하여 쿼리를 실행시키는 것과
dataSource로 TransactionManager
를 생성하고 TransactionTemplate
을 생성하여 쿼리를 실행시키는 것의
트랜잭션 동기화 저장소를 사용하는 차이점은 알겠지만 확실한 (각 클래스들의)차이점을 알진 못 하겠다.
7장에서 개인적으로 SQL을 수정하는 기능을 추가하면서 UpdatableSqlRegistry
인터페이스를 추가하고
SqlRegistry
를 추상화 한것이 인상깊었다.
-
ConcurrentHashMap
을 사용한 구현체와내장형 디비
를 사용한 구현체를 추가한 것
- 예외검증을 위한 AOP가 실제로 현업에서 사용되는가?
-
@Configurable
실제로 도메인에 DI를 위해 사용하는 경우가 있나? - 당신의 코드는 POJO하신가요?
- 코드스피츠 - 오브젝트