import java.sql.SQLException;
import com.jinsu.springframe.dao.UserDao;
import com.jinsu.springframe.domain.User;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class UserDaoTest {
private UserDao dao;
private User user1;
private User user2;
private User user3;
@BeforeEach
public void setUp() {
ApplicationContext context = new AnnotationConfigApplicationContext("com.jinsu.springframe.dao.DaoFactory");
this.dao = context.getBean(UserDao.class); // Simplified bean retrieval
this.user1 = new User("gyumee", "박성철", "springno1");
this.user2 = new User("leegw700", "이길원", "springno2");
this.user3 = new User("bumjin", "박범진", "springno3");
}
@Test
public void andAndGet() throws SQLException {
dao.deleteAll();
Assertions.assertEquals(0, dao.getCount(), "Initial count should be 0");
dao.add(user1);
dao.add(user2);
Assertions.assertEquals(2, dao.getCount(), "Count after adding users should be 2");
User userget1 = dao.get(user1.getId());
Assertions.assertEquals(user1.getName(), userget1.getName(), "User1 name should match");
Assertions.assertEquals(user1.getPassword(), userget1.getPassword(), "User1 password should match");
User userget2 = dao.get(user2.getId());
Assertions.assertEquals(user2.getName(), userget2.getName(), "User2 name should match");
Assertions.assertEquals(user2.getPassword(), userget2.getPassword(), "User2 password should match");
}
@Test
public void getUserFailure() throws SQLException {
dao.deleteAll();
Assertions.assertEquals(0, dao.getCount(), "Initial count should be 0");
// Using assertThrows to test for expected exception
Assertions.assertThrows(EmptyResultDataAccessException.class,
() -> dao.get("unknown_id"),
"Getting a user with unknown_id should throw EmptyResultDataAccessException"
);
}
@Test
public void count() throws SQLException {
dao.deleteAll();
Assertions.assertEquals(0, dao.getCount(), "Initial count should be 0");
dao.add(user1);
Assertions.assertEquals(1, dao.getCount(), "Count after adding first user should be 1");
dao.add(user2);
Assertions.assertEquals(2, dao.getCount(), "Count after adding second user should be 2");
dao.add(user3);
Assertions.assertEquals(3, dao.getCount(), "Count after adding third user should be 3");
}
}
디자인 패턴에서 main 메소드를 client라고 한다.
CSVMetadataCollector
CSV - 2차원data
database = 2차원 data
메타데이터 : 어떤정보
PROTOBUF_FETCH : 구글에서 만듬
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
1. 타이트 커플링 (Tight Coupling)
• 정의: 타이트 커플링은 클래스나 모듈 간에 강한 의존성이 있는 경우를 의미합니다. 즉, 하나의 클래스가 다른 클래스에 직접적으로 의존하거나, 구현 세부 사항에 대한 지식을 가지는 경우입니다.
• 특징:
• 직접 의존성: 클래스가 다른 클래스의 구체적인 구현에 의존합니다.
• 변경 어려움: 한 클래스의 변경이 다른 클래스에도 영향을 미칠 수 있습니다.
• 유연성 부족: 시스템이 커질수록 유지 보수가 어려워집니다.
2. 루즈 커플링 (Loose Coupling)
• 정의: 루즈 커플링은 클래스 간의 의존성을 줄이고, 상호 작용을 최소화하여 서로 독립적으로 유지되도록 설계하는 방식입니다. 이는 인터페이스나 추상 클래스를 사용하여 구현됩니다.
• 특징:
• 간접 의존성: 클래스가 다른 클래스의 구체적인 구현에 의존하지 않고, 인터페이스나 추상 클래스에 의존합니다.
• 변경 용이성: 하나의 클래스가 변경되더라도 다른 클래스에 미치는 영향이 적습니다.
• 유연성 증가: 시스템의 유지 보수와 확장이 용이합니다.
JSON은 JavaScript Object Notation의 약자로, 데이터 교환을 위한 경량의 텍스트 형식입니다. JSON은 인간이 읽기 쉬우면서도 기계가 파싱하고 생성하기 쉬운 형식으로 설계되었습니다. JSON은 주로 웹 애플리케이션에서 서버와 클라이언트 간의 데이터 교환을 위해 사용됩니다.
JSON의 기본 구조
JSON은 두 가지 기본 데이터 구조로 구성됩니다:
1. 객체 (Object): 이름-값 쌍의 집합으로, 중괄호 {}로 감싸입니다.
2. 배열 (Array): 값의 순서 있는 목록으로, 대괄호 []로 감싸입니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
CSV메타데이터는 제이슨 xml 프로토버퍼 이런것들을 하나하나 다 만들어 줘야됨 (강한 결집력) -> 타이트 커플링
-> 제이슨 프로토버퍼 이런것들에 의해 디펜던시s 한다(직접만들어서)
-> new 연산자를 써서 직접 컨트롤
CSV메타데이터와 상호작용하던 클래스들이 하나하나 다 사라짐 why? (루즈 커플링)
-> 루즈커플링은 어떻게 처리하냐? 내부가아니라 외부에서 다 만들어준다. 어디서? 클라이언트(메인메서드)가 만들어줌!
-> 셋메타데이터컬렉터라는 애가 주입을 한다.
-> 메서드에 의한 dependency injection이 수행됨
-> IoC : 제 3자에 의해 만들어짐(제어의 역전) inverse of control
-> 클라이언트가 만들었다.(메인클라이언트가 직접 만들고 셋메타데이타컬렉터라는 애한테 주입이 됨->메서드에 의한 dependency injection이 수행되었다고 칭함)
-> 외부에서 제공되는 패치에 의해서 쓰겠다~
-> 패치는 데이터를 뽑아온다
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
IoC 컨테이너(Inversion of Control Container)는 객체의 생성, 관리, 그리고 의존성 주입을 자동으로 처리해주는 소프트웨어 디자인 패턴입니다. 주로 의존성 주입(Dependency Injection)과 제어의 역전(Inversion of Control) 원칙을 활용하여 객체 지향 프로그래밍에서의 복잡성을 줄이고, 코드의 재사용성과 테스트 용이성을 높이는 데 사용됩니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
spring framework를 쓰는 이유? 코딩할 때 노가다를 하지않기 위해서..?;
static 각 클래스 객체에 의해 공유
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
싱글턴 디자인 패턴(Singleton Design Pattern)은 클래스의 인스턴스가 오직 하나만 생성되도록 보장하고, 이 인스턴스에 전역적으로 접근할 수 있도록 하는 패턴입니다. 이 패턴은 특정 클래스의 인스턴스가 시스템 전체에서 유일해야 할 때 유용합니다.
싱글턴 패턴의 주요 특징
1. 단일 인스턴스:
• 클래스의 인스턴스가 하나만 존재해야 함을 보장합니다.
2. 전역 접근:
• 클래스의 인스턴스에 전역적으로 접근할 수 있는 방법을 제공합니다.
3. 지연 초기화:
• 필요할 때까지 인스턴스를 생성하지 않고, 최초 요청 시 생성합니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
intstance 임플리멘테이션 펄스펙티브
메서드시그니처 - 메서드이름 + 메서드파라미터 : 메서드시그니처는 리턴값 포함안됨
JPA는 ORM을 구현했다
JPA
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
**엔티티(Entity)**는 데이터베이스와 객체 지향 프로그래밍에서 사용되는 개념으로, 주로 데이터베이스의 테이블과 자바 객체 간의 매핑을 처리하는 데 사용됩니다. 특히 자바에서의 엔티티는 JPA (Java Persistence API)와 관련이 깊습니다.
dbms - 관계형 데이터베이스
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
jdbc의 메인 api는?
1. DriverManager
2. Connection
3. Statement
4. PreparedStatement
5. CallableStatement
6. ResultSet
JDBC는 자바 애플리케이션에서 데이터베이스와의 상호작용을 처리하기 위한 API로, DriverManager, Connection, Statement, PreparedStatement, CallableStatement, ResultSet 등의 주요 클래스를 포함합니다. 이들 클래스를 사용하여 데이터베이스에 연결하고, SQL 쿼리를 실행하며, 결과를 처리할 수 있습니다. JDBC는 자바 애플리케이션에서 관계형 데이터베이스와 효과적으로 상호작용하는 데 필수적인 도구입니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
set은 중복을 허용하지않는 컬렉션 타입임.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
DI의 주요 방식
1. 생성자 주입 (Constructor Injection)
• 설명: 객체를 생성할 때 의존성을 생성자의 매개변수로 주입합니다.
• 장점: 의존성이 불변이 되며, 객체가 생성될 때 모든 의존성이 주입되므로 객체가 완전히 초기화된 상태로 보장됩니다.
2. 세터 주입 (Setter Injection)
• 설명: 객체 생성 후 세터 메서드를 통해 의존성을 주입합니다.
• 장점: 의존성을 선택적으로 설정할 수 있으며, 객체 생성 후에도 의존성을 변경할 수 있습니다.
• 단점: 객체가 완전히 초기화되기 전에는 의존성이 설정되지 않으므로, 객체 상태가 불완전할 수 있습니다.
3. 필드 주입 (Field Injection)
• 설명: 클래스의 필드에 직접 의존성을 주입합니다.
• 장점: 설정이 간단하고 코드가 간결합니다.
• 단점: 의존성이 명시적으로 드러나지 않으며, 필드에 직접 접근하기 때문에 객체의 불변성을 보장하기 어렵습니다.
4. 인터페이스 주입 (Interface Injection)
• 설명: 의존성을 주입받는 객체가 특정 인터페이스를 구현하고, 해당 인터페이스를 통해 의존성을 주입받습니다.
• 장점: 의존성을 주입하는 방식이 명확하게 정의됩니다.
• 단점: 인터페이스를 추가로 정의해야 하며, 구현이 복잡해질 수 있습니다.
DI의 장점
1. 결합도 감소: 객체 간의 직접적인 의존 관계를 줄이고, 외부에서 의존성을 주입하여 모듈 간의 결합도를 낮출 수 있습니다.
2. 유연성 증가: 객체의 의존성을 외부에서 주입하므로, 변경이나 확장이 쉬워집니다.
3. 테스트 용이성: 의존성을 주입받아 테스트용 목(Mock) 객체를 주입하는 등의 테스트가 용이합니다.
4. 코드의 재사용성: 재사용 가능한 컴포넌트를 쉽게 생성할 수 있습니다.
DI 프레임워크
• Spring Framework: 스프링 프레임워크는 DI를 기본으로 지원하며, 애플리케이션의 컴포넌트를 관리하고 의존성을 주입하는 기능을 제공합니다.
• Google Guice: 구글이 개발한 DI 프레임워크로, 간단한 설정과 강력한 의존성 주입 기능을 제공합니다.
• Dagger: Android 및 자바에서 의존성 주입을 지원하는 DI 프레임워크로, 컴파일 타임에 의존성을 해결합니다.
결론
DI는 객체 지향 프로그래밍에서 객체 간의 의존성을 관리하고 주입하는 방식으로, 코드의 결합도를 낮추고 유연성을 높이는 데 중요한 역할을 합니다. 다양한 DI 방식과 프레임워크를 통해 애플리케이션의 설계를 더욱 모듈화하고 유지보수하기 쉽게 만들 수 있습니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
ioc컨테이너는 철저하게 루즈커플링
Spring IoC Container 한테 부탁을 해서 런타임 때 자동으로 생성을 해주는 역할을 함
BeanFactory / ApplicationContext
BeanFactory : 모든타입의객체를 생성/ 라이프사이클/ 싱글턴타입,프로토타입 -> BeanFactory 인터페이스 구체가 수행을 한다
ApplicationContext : BeanFactory를 상속한 인터페이스
-> WebApplicationContext 궁극적으로 이것을 사용하기위해서
컨피그레이션 중요!
ApplicationContext = Spring IoC Container
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
***
Spring에서 애플리케이션의 중추를 형성하고 Spring IoC 컨테이너에 의해 관리되는 객체를 빈(Bean)이라고 합니다. 빈은 Spring IoC 컨테이너에 의해 인스턴스화되고, 조립되고, 관리되는 객체입니다. 그렇지 않으면 빈은 애플리케이션의 많은 객체 중 하나일 뿐입니다. 빈과 그들 사이의 의존성은 컨테이너에서 사용되는 구성(컨피그레이션) 메타데이터에 반영됩니다.
***
POJO는 자바의 Object 클래스만 상속을 한다(다이렉트 슈퍼클래스로 자바의 오브젝트 클래스만 가진다)
컨피그레이션 메타데이터 사용을 잘 안한다
- Annotation-based configuration: 애플리케이션의 컴포넌트 클래스에 Annotation-based 구성 메타데이터를 사용하여 Bean을 정의합니다.
- Java-based configuration: Java 기반 configuration 클래스를 사용하여 애플리케이션 클래스 외부에 Bean을 정의합니다. 이러한 기능을 사용하려면 @Configuration, @Bean, @Import 및 @DependsOn 어노테이을 참조하세요.-> 이거 두개만 사용을 하는편
노가다를 최소화하기 위해서 -> AOP기술
**CGLIB (Code Generation Library)**는 자바에서 런타임에 클래스를 생성하고 수정하는 데 사용되는 라이브러리입니다. 주로 스프링 프레임워크에서 동적으로 프록시 객체를 생성하는 데 활용됩니다. CGLIB는 주로 인터페이스가 없는 클래스에 대한 프록시를 생성할 때 사용됩니다.
CGLIB의 주요 개념
1. 프록시(Proxy)
• 프록시는 특정 객체를 감싸고, 그 객체에 대한 접근을 제어할 수 있는 객체입니다. 주로 로깅, 트랜잭션 관리, 보안과 같은 기능을 적용할 때 사용됩니다.
2. 바이트코드 조작
• CGLIB는 자바 바이트코드를 동적으로 생성하고 수정할 수 있습니다. 이를 통해 클래스의 서브클래스를 생성하거나 기존 클래스를 수정할 수 있습니다.
3. 런타임 프록시
• CGLIB는 런타임에 클래스의 서브클래스를 생성하여, 실제 객체의 메서드를 오버라이드하고, 프록시 메서드를 추가합니다. 이를 통해 기존 클래스에 새로운 기능을 추가할 수 있습니다.
Spring Framework에서의 CGLIB 사용
스프링 프레임워크에서 CGLIB는 주로 다음과 같은 경우에 사용됩니다:
1. 메서드 호출 트랜잭션 관리
• CGLIB는 @Transactional 애너테이션이 붙은 메서드의 트랜잭션을 관리하기 위해 사용됩니다. 이 경우, CGLIB는 해당 클래스를 상속받는 서브클래스를 생성하여 메서드 호출을 가로채고 트랜잭션을 관리합니다.
2. AOP (Aspect-Oriented Programming)
• 스프링 AOP에서는 CGLIB를 사용하여 비즈니스 로직에 횡단 관심사를 추가합니다. CGLIB는 대상 클래스의 서브클래스를 생성하고, 어드바이스(Advice)를 삽입하여 메서드 호출 시 해당 어드바이스가 실행되도록 합니다.
CGLIB 프록시 사용 예제
스프링에서 CGLIB 프록시를 사용하는 설정은 @EnableAspectJAutoProxy(proxyTargetClass = true)를 통해 설정할 수 있습니다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
import org.springframework.jdbc.datasource.SimpleDriverDataSource; -> pringframework.jdbc.datasource 지원
->
Connection c = DriverManager.getConnection(
"jdbc:mysql://localhost/sbdt_db?characterEncoding=UTF-8",
"root",
"wlstnek123");
이제 이거를 쓰지 않겠다...
기존에는 데이터베이스.드라이버를 이용해서 mysql에 연결을 하였지만 이제는 스프링프레임워크에 포함되어 있는 jdbc를 이용한 데이터소스(데이터베이스)를 이용하여 사용
jdbc 데이터베이스 드라이버 대신에 데이터소스를 사용하겠다...
com.mysql.cj.jdbc.Driver -> 우리가 jdbc api 인터페이스 구체들을 다운받았다.
스프링프레임워크를 쓰는이유? 우리의 비즈니스 로직에 집중할려고...(생산성향샹), s/w개발 생산성 향상
JDBC API (드라이브매니저,커넥션,커리의응탑 -> 리절트셋)쓰는이유? 우리의 비즈니스 로직에 집중할려고... 위와 같다
-> 데이터베이스를 사용하기 위해서
-> 관계형 데이터베이스 RDMS,MySQL,H2(제조사들) 등등... and NoSQL (Not only SQL)
-> 특정 contact(JDBC API : 인터페이스 덩어리) 표준을 따른다. / 인터페이스는 계약(contact, 표준)
-> 데이터베이스와 CRUD(생성, 읽기, 갱신, 삭제)
-> 인터페이스는 구체(계약)
내가 드라이브매니저 쓰기싫다 -> 데이터소스를 써라
드라이브매니저를 사용해서 하는거보다 데이터소스가 더 심플하다(편의성 why? JDBC구체를 깔고 시작*)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
TDD의 기본 사이클: Red-Green-Refactor
JUnit 5 - 개발자가 소프트웨어의 작은 부분을 독립적으로 테스트 할 수 있게 해주는 도구로, 소프트웨어 개발 과정에서 중요한 역할을 함
jar파일로 앱에 참여하고있음.
'Note-Taking' 카테고리의 다른 글
Instrumentation API 정리 (0) | 2024.09.03 |
---|---|
Spring Framework에서 테스트 어노테이션과 자바 기반 설정의 역할 정리 (0) | 2024.08.09 |
Java 클래스 구조 정리 (0) | 2024.08.07 |
Java의 기본 정리 (0) | 2024.08.05 |
Java 입문 정리 (0) | 2024.07.11 |