I. DI
1. XML
(1) XML 정리
- 컨테이너에다가 Bean 객체를 만들수 있다.
- 이 경우 우리가 bean 객체를 읽을 경우 클래스명이 아니라, name 속성으로 손쉽게 가능하다
- 원래 가져올 때는 구현체를 가지고 와야하지만, 이를 이용하면 인터페이스 명으로 가능하다
1)
XML 로 객체를 만드는 방식
<bean name="repository" class="kr.co.rland.web.repository.mybatis.MbMenuRepository"/>
<bean name="service" class="kr.co.rland.web.service.DefaultMenuService">
<property name="repository" ref="repository" ></property>
</bean>
serivce name을 붙여서 bean 객체를 읽을 수있다.
<program.java>
MenuService service = (MenuService) context.getBean("service");
List<Menu> list = service.getList();
2)
xml 하나씩 읽는데 번거로워 이를 읽어주는 parser가 있음 (마치 json parser처럼) 이런 parsing한 것들을 담으면 container가 된다.
즉 XML으로 DI역할 해주는게 스프링인데, 내가 객체 직접 안만들고 new 해서 하기보다 context.getBean()으로 가능해!
================================================================
2. Annotation
(1) XML의 단점
XML 사실 옛날버전이기도 하고, 단점이 커!
단점은 bean 객체 만들 때 보따리(container)에 담아달라고 해야해!
담아달라는 설정을 다른 외부 파일(context.xml)에 해야한다. 내가 설정을 다른 디렉토리로 하면 일이 두번이 돼
별도의 파일에 가서 등록 해달라고 말하는거야
(2) Annotation의 의의
처리기 인데, 이는 코드를 심어놓는 설정이야 (예컨데, 파서나 번역기 만들 때 코드에 심음)
XML 방식 파싱의 경우 XML에다가 기재를 해야하는것과 더불어 XML을 먼저 실행해야한다.
그러나 어노테이션 방식의 경우 코드에 작성되어있는지 여부만 확인 후 파싱이 적용된다
(3) Annotation의 장점
1)
XML 은 매번 설정을 고치는 것은 힘들다 (연쇄적으로 고쳐준다 : 불편함)
이러한 설정을 대신하는게 없을까 해서 나온게 어노테이션 설정이다,
xml 대신 Annotation방식으로 하면
별도파일 안둬도 되고, 그 파일을 어디 뒀는지 처리기에 알려줄 필요 없어
둘중 무엇이든 정의는 parser가 하는거고 그 형식을 이해하는거야
2)
parser를 만들고, 이에대해서 어노테이션을 이용해보자
<program.java>
public class program {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
ApplicationContext context = new ClassPathXmlApplicationContext("kr/co/rland/web/di/context.xml");
// MenuRepository menurepo = context.getBean(MenuRepository.class);
// List<Menu> list = menurepo.findAll();
// System.out.println(list);
MenuService repo2 = (MenuService) context.getBean("service");
List<Menu> list = repo2.getList();
System.out.println(list);
Menu menu = new Menu();
menu.setId(1);
menu.setName("아메아메");
menu.setPrice(5000);
JSONParser parser = new JSONParser(menu);
String json = parser.toJSON();
System.out.println(json);
}
}
parser 클래스에서 toJson()을 이용한다.
<JSONParser.java>
package kr.co.rland.web.entity;
import java.lang.reflect.Field;
public class JSONParser {
private Object entity;
public JSONParser() {
// TODO Auto-generated constructor stub
}
public JSONParser(Object entity) {
this.entity = entity;
}
public String toJSON() throws IllegalArgumentException, IllegalAccessException {
StringBuilder builder = new StringBuilder();
builder.append("{");
Field[] fields = entity.getClass().getDeclaredFields();
for(Field f : fields) {
String name = f.getName();
// Column col = f.getAnnotation(Column.class);
//
// System.out.println("1 :"+ col);
//
// if(col != null)
// name = col.value();
//
//
f.setAccessible(true);
Object value = f.get(entity);
String fieldValue = String.format(" \"%s\" : \"%s\" ", name,value);
builder.append(fieldValue);
builder.append(",");
}
builder.append("}");
String json = builder.toString();
return json;
}
}
여기서 StringBulder 를 쓰는이유는 뭘까?
자바의 기존 String은 변경불가능한 문자열(문자열 연결새 새로운 문자열을 생성하고, 이전 것들은 가바지 컬렉터로 감)과 달리
StringBuilder는 변경가능한 문자열이다.
Field 클래스는(자바 리플랙션) 클래스에 있는 변수의 정보를 제공하기 위한 것이다.
setAccessible 은 private 멤버변수를 read/write를 가능할지 여부에 대해서 다루는 것이다.
Field 자료형에서 필드 값들을 받는다.
3)
이 경우 어노테이션을 이용해서 (@Column) 출력되는 이름을 쉽게 변경할 수있다
<Column.java>
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)\
//애너테이션 정의
public @interface Column {
//애너테이션 요소선언
String value();
}
여기에 있는 Annotation 은 개발자가 개별적으로 정의한 자바의 어노테이션이다
@interface 애너테이션이름
이 부분은 interface정의하는 방법에서 @를 붙이는것이 추가된것이 불과핟.
@Target 은 Annotation이 적용가능한 대상을 누구인지 지정하기 위한것이다.
ElementType.FIELD의 경우 TYPE.FIELD로 줄여서도 쓸수있다. 이 의미는 적용대상이 FIELD인 경우 사용이 가능하다
@Retention 은 유지되는 기간을 지정하는데 사용이된다.
유지정책은 세가지가 존재한다 소스파일만존재/ 클래스파일만존재, 실행불가/실행가능 이다
여기서 RUNTIME은 실행시인데, 주로 리플렉션으로 Annotation정보 읽어서 처리가 가능하다.
<Menu.java>
public class Menu {
@Column("ID")
private long id;
private String name;
private int price;
@Column("reg_Date999")
private Date regDate;
private int categoryId;
private long regMemberId;
필드멤버들중 id, regDate부분을 Annotation 을 이용하면 실제 그 멤버명을 변경할 수있다.
여기서 @Column("ID")는 실제로 @Column(value = "ID") 와 동일한 것이다.
왜냐 Column 애너테이션의 요소가 value로 하나이면서 본 이름이기 때문이다.
<JSONParser.java>
//생성자에서 받은 entity멤버는 model(Menu)로서 받는다.
for(Field f : fields) {
String name = f.getName();
//어노테이션을 받아오는 부분 (해당 클래스의 멤버 중 어노테이션이 붙은 부분을 찾는다)
Column col = f.getAnnotation(Column.class);
System.out.println(" 1:"+ col);
//각 멤버 중에서 어노테이션이 있는 경우에
if(col != null)
//name에 별칭인 것으로 변경시켜준다
name = col.value();
f.setAccessible(true);
Object value = f.get(entity);
String fieldValue = String.format(" \"%s\" : \"%s\" ", name,value);
builder.append(fieldValue);
builder.append(",");
}
여기서 어노테이션(별칭)이 있는지를 확인하고, 있다면 그 별칭으로 변경시켜준다.
(즉 : RegDate -> reg_date999 / id -> ID)
(4) 스프링의 Annotation 을 이용한 Spring DI (설정)
1)
스프링 제공, bean객체 생성 5가지 Annotation이 있다.
HTML 의 시맨틱 태그처럼 각각 콩자루 중에서 얘는 서비스 콩, 컨트롤러 콩 등으로 의미가 추가된거야!
5개는 무엇이든 하든 동일 함! 의미만 부여한것에 불과해!
우리는 어떤것을 쓸때 Bean을 한다.
2)
@Componet와 다른 Annotation으로 대별될 수있다.
다른 @Componet대신에 다른 Annotation을 이용이 가능하다.
//@Component
// @Controller // 주소매핑이 추가된것
//
//
// @Service
// @Repository
// @Configuration //얘 자체 의미보다, 안에 bean 이라는 어노테이션 담고있어
// @Bean // 남의 코두 주석 달수없는 경우 confi이용해서 Bean으로 한
//다른것으로 바꿔어도 됨
@Configuration
public class Config {
// @Bean만 간단히 쓰면 추가로 IOC 컨테이너에 빈 객체가 생성된다.
// 반환이 new에 의해서 객체가 생성된다. 여기서 객체는 빈 객체이다.
// 이때, IOC 컨테이너가 이것을 읽을 수 있게 Annotation 어플리케이션 컨텍스트를 이용하자!
@Bean
public jdbcMenuRepository repository() {
return new jdbcMenuRepository();
}
@Bean
public List list() {
return new ArrayList();
}
@Bean
public String hello() {
return "hello 콩자루?";
}
}
@config Annotation은 다른것으로 바뀌어도 상관은없다
이 경우 @config 와 @Bean에서
먼저 Config가 메모리에 올라가고 후에 Bean Annotation한 것이 메모리에 올라간다
이 경우 bean 객체를 담고자 하면 retrun 에 new로 객체의 이름 반환하면 만들어진다.
즉 IoC컨테이너에 빈객체가 생성됨
한편 @configuration 인 이유는 설정을 담고있어서 이다.
--
[!!: 하지만 나의 경우 이러한 오류가 발생한다.]
(5) 스프링의 Annotation 을 이용한 Spring DI 연결
1)
Autowired
일반적으로 같은 객체 2개를 두는건 문제가 있어!
매핑, 오토와이어드 하려고하는데 2개이면 모호하다는 메시지가 발생한다
필드에다가 하는 것과 , 세터, 생성자에 하기 셋 중 어디에 하는게 가장 좋을까?
- 세터에 오토와이어드(D.I)하면 장점?
DI 가 된다는 것은 setter 호출한다는거야! 바인딩 되기전에 다른작업을 처리할 수있는 것이다
- 필드에 하면 autowired만 되지 뭔가가 실행되는건 없어! 코드수가 가장적은 이점이 있다.
- 생성자도 함수역할을 할 수있기 때문에 할 일이 있을 수 있어!
우리는 필드에다가 할거야 : 왜냐 코드수가 가장 적기 때문이야.
2)
repository는 컨트롤러가 쓰고있자나,
그런데 우리가 사용하는 repository가 다른 곳인데,
오토와이어드 하려면 얘가 메모리에 올라가 있어야(@Component)해
즉 @Autowired 했지만, 콩자루에 담겨 있지 않은 상황
-- 3)
스프링은 앞으로 XML 을 이용하는 방식은 이용하지 않을거야!
- 그런데 스프링부트3이 쓰는 스프링버전은 6이다. 회사갔는데 XML방식 쓰는곳은 주로 4버전 이하야!
어노테이션에 익숙해지자
@component가 기본이야, 남에꺼 올린다면은 @configuration 을 써!
이것을 쓰는이유는 의미를 부여한거야! 이거를한다는것은 다른콩자루에 담을 목록이 있다는거야!
콩자루 담을 때 bean객체를 써! bean 어노테이션은 configu에 주로 쓰는걸로 약속한거야!
각 Annotation 역할을 구분하기 세분화한거야 각각에 이해하자!
4)
<DefaultMenuService.java>
package kr.co.rland.web.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import kr.co.rland.web.entity.Menu;
import kr.co.rland.web.repository.MenuRepository;
@Component
public class DefaultMenuService implements MenuService {
@Autowired
private MenuRepository repository;
public void setRepository(MenuRepository repository) {
this.repository = repository;
}
@Override
public List<Menu> getList() {
return repository.findAll();
}
}
<MenuController.java>
@Controller("adminMenuController")
@RequestMapping("/admin/menu/")
public class MenuController {
@Autowired
//콩자루 가져 올 준비 => 결합! 을 의미 해
// 구현체를 쓰면안돼 결합력이 강해지기 때문이야!
// private MenuRepository menuRepository;
private MenuService service;
<jdbcMenuRepository.java>
package kr.co.rland.web.repository.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import kr.co.rland.web.entity.Menu;
import kr.co.rland.web.repository.MenuRepository;
@Repository
public class jdbcMenuRepository implements MenuRepository{
@Autowired
private DataSource dataSource;
@Override
public List<Menu> findAll() {
//가져온다 : 라이브러리가 해결할 수 있는것이 아니기 때문!
String sql = "select id, name, price, regDate, categoryId from menu";
이런 3가지 에시로 bean 객체에 담은것으로 autowired를 통해서 결합이 가능해!
2. 스프링 트랜잭션
MVC / DI / 트랜잭션 등 총 4가지가 있어
II. MyBatis
(1) 들어가며
1)
JPA 와 같은 진영이야!
스프링이 제공하는것도 마음에 들지만 MyBatis를 이용할거야!
좋은라이브러리란 극단적으로 내가 코드를 안쓰게끔 하는거야 그러려면 내 입맛에 맞게 쓸수없다 더 좋은라이브러리는 안쓰면서 내입맛에 쓸수있다
JPA는 누더기가 많고, 수정이 복잡해 그런데 마이바티스는 안그래
2)
마이바티스를 부트 스타터에서 실행하자!
(2) datasource를 이용해서 DB정보 한번에 세팅하기
1)
application.properties에서 DB정보를 입력하자
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=200MB
spring.datasource.url=jdbc:mariadb://db.newlecture.com:3306/rlanddb
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.username=rland
spring.datasource.password=20220823
2)
이렇게 하면 repository 에서 설정을 하지않아도 dataSource로 곧바로 가능하다.
@Repository
public class jdbcMenuRepository implements MenuRepository{
@Autowired
private DataSource dataSource;
@Override
public List<Menu> findAll() {
//가져온다 : 라이브러리가 해결할 수 있는것이 아니기 때문!
String sql = "select id, name, price, regDate, categoryId from menu";
// DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
// dataSourceBuilder.driverClassName("org.mariadb.jdbc.Driver"); //사용자 계정
// dataSourceBuilder.url("jdbc:mariadb://db.newlecture.com:3306/rlanddb");
// dataSourceBuilder.username("rland"); //이부분 바꿔주면 됨!
// dataSourceBuilder.password("20220823");
//
// DataSource dataSource = dataSourceBuilder.build();
JdbcTemplate template = new JdbcTemplate(dataSource);
List<Menu> list = template.query(sql, new BeanPropertyRowMapper(Menu.class));
return list;
}
3)
이런경우 Mybatis는 Repository interface의 구현부가 필요없음!
4)
yml (야믈) 표기
구조를 확인할 수있는 이점이 있다.
이는 보통 설정파일이 많아서 복잡할때 쓰인다! JPA를 이용한 스프링부트 프로젝트에서 쓰임!
(3) 수업중 문제
버전 다운그레이드
1. 보충
(1) StringBuilder
- 가변문자열
(2) 자바 자체의 어노테이션 (target / retention)
두개의 경우 메타어노테이션 (어노테이션을 정의하는 어노테이션) 이다.
target은 어디에다가 어노테이션을 설정해줄지 (멤버? 클래스 등)
retention은 유지정책 관련 언제까지 유지할지?
(3) 어노테이션이 어떻게 활약?
소스코드에 문서만들기보다, 소스코드와 문서를 하나의 파일로 관리하기 위함임
2. 회고
1) 어려움이 크다. 일단 수업시간에 집중이 안되는데, 이전 선수내용을 이해가 어느정도 필요하다는게 더욱더 크게 느껴진다.
'배움 __IL > TIL 1기' 카테고리의 다른 글
TIL : 63번째- 230307 [3-1-화] (0) | 2023.03.07 |
---|---|
TIL : 62번째- 230304 [3-1-월] (0) | 2023.03.06 |
TIL : 60번째- 230228 [2-4-화] (0) | 2023.02.28 |
TIL : 58번째- 230224 [2-3-금] (0) | 2023.02.24 |
TIL : 57번째- 230223 [2-3-목] (0) | 2023.02.23 |