스프링

 

@Autowired 애노테이션의 필수 여부 

 

dateTimeFormatter 필드가 null이면 날짜형식을 %tF로 출력하고 이 필드가 null이아니면 dateTimeFormatter를 이용해서 날짜 형식을 맞춰  출력하도록 print()메서드 수정 

밑에 코드를 보면 세터 메서드에 @Autowired 애노테이션을 주지 않아야 정상작동됨 왜냐하면 스프링설정클래스에 

자동 주입 할 @Bean이 없기 때문에 익셉션 발생 

 

package spring;

import java.time.format.DateTimeFormatter;

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter() {
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}
	
	public void print(Member member) {
		if (dateTimeFormatter == null) {
			System.out.printf(
					"회원 정보: 아이디=%d, 이메일=%s, 이름=%s, 등록일=%tF\n", 
					member.getId(), member.getEmail(),
					member.getName(), member.getRegisterDateTime());
		} else {
			System.out.printf(
					"회원 정보: 아이디=%d, 이메일=%s, 이름=%s, 등록일=%s\n", 
					member.getId(), member.getEmail(),
					member.getName(), 
					dateTimeFormatter.format(member.getRegisterDateTime()));
		}
	}
	
	@Autowired
	public void setDateFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}
	
}

 

이렇게 자동 주입할 대상이 필수가 아닌 경우에는 3가지 방법이있다. ( 필수 여부 지정하는 방법 )

 

1.

@Autowired 애노테이션의 required 속성을 false로 지정

false로 지정하면 매칭되는 빈이 없어도 익셉션이 발생하지 않으며 자동 주입을 수행하지 않는다.

나중에 유지보수를 위해 해당처럼 사용해도 괜찮음

	@Autowired(required = false)
	public void setDateFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}

 

 

2.

스프링 5버전부터는 위에 처럼 말고 의존 주입 대상에 자바 8의 Optional 사용해도 된다.

일치하는 빈이 존재하지 않으면 값이 없는 Optional을 인자로 전달하고 ( 익셉션 발생되지 않음 )

일치하는 빈이 존재하면 해당 빈을 값으로 갖는 Optional을 인자로 전달

	@Autowired
	public void setDateFormatter(Optional<DateTimeFormatter>formatterOpt) {
		this.dateTimeFormatter = dateTimeFormatter;
	}

 

3.

@Nullable 애노테이션 사용 ( 스프링이 제공하는 애노테이션 ) 

스프링 컨테이너는 세터 메서드를 호출할 때 자동 주입할 빈이 존재하면 해당 빈을 인자로 전달하고,

존재하지 않으면 인자로 null을 전달

	@Autowired
	public void setDateFormatter(@Nullable DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}

 

3가지 방식은 필드에도 그대로 적용 가능 

1.

public class MemberPrinter {
	@Autowired(required = false)
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter() {
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}

 

2.

public class MemberPrinter {
	@Autowired
	private Optional<DateTimeFormatter>formatterOpt;
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter() {
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}

 

3.

public class MemberPrinter {
	@Autowired
	@Nullable
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter() {
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}

 

 

 

 

 

생성자 초기화와 필수 여부 지정 방식 동작 이해

밑에 코드 @Autowired(required = false)

info 출력 시 기본 생성자에서 초기화한 dateTimeFormatter를 사용해서 회원가입 일자 출력

package spring;

import java.time.format.DateTimeFormatter;

import org.springframework.beans.factory.annotation.Autowired;

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter() {
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}
	
	public void print(Member member) {
		if (dateTimeFormatter == null) {
			System.out.printf(
					"회원 정보: 아이디=%d, 이메일=%s, 이름=%s, 등록일=%tF\n", 
					member.getId(), member.getEmail(),
					member.getName(), member.getRegisterDateTime());
		} else {
			System.out.printf(
					"회원 정보: 아이디=%d, 이메일=%s, 이름=%s, 등록일=%s\n", 
					member.getId(), member.getEmail(),
					member.getName(), 
					dateTimeFormatter.format(member.getRegisterDateTime()));
		}
	}
	
	@Autowired(required = false)
	public void setDateFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}
	
}

 

 

 

 

밑에 코드 @Nullable

info 출력 시 dateTimeFormatter가 null일 때 결과가 출력 

package spring;

import java.time.format.DateTimeFormatter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter() {
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}
	
	public void print(Member member) {
		if (dateTimeFormatter == null) {
			System.out.printf(
					"회원 정보: 아이디=%d, 이메일=%s, 이름=%s, 등록일=%tF\n", 
					member.getId(), member.getEmail(),
					member.getName(), member.getRegisterDateTime());
		} else {
			System.out.printf(
					"회원 정보: 아이디=%d, 이메일=%s, 이름=%s, 등록일=%s\n", 
					member.getId(), member.getEmail(),
					member.getName(), 
					dateTimeFormatter.format(member.getRegisterDateTime()));
		}
	}
	
	@Autowired
	public void setDateFormatter(@Nullable DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}
	
}

일치하는 빈이 없으면 값 할당 자체를 하지 않는 @Autowired(required = false)와 달리 @Nullable 애노테이션을 사용하면 일치하는 빈이 없을 때 null 값을 할당한다. 기본 생성자에서 자동 주입 대상이 되는 필드를 초기화할 때는 이 점에 유의 

 

 

 

 

 

 

컴포넌트 스캔

컴포넌트 스캔은 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능이다. 설정 클래스에 빈으로 등록하지 않아도 

원하는 클래스를 빈으로 등록할 수 있으므로 컴포넌트 스캔 기능을 사용하면 설정 코드가 크게 줄어든다.

 

1. @Component 애노테이션으로 스캔 대상 지정

스프링이 검색해서 빈으로 등록할 수 있으려면 클래스에 @Component 애노테이션을 붙어야 한다.

해당 클래스를 스캔 대상으로 표시 

 

MemberDao 클래스

@Component
public class MemberDao

 

ChangePasswordService 클래스 

@Component
public class ChangePasswordService {

MemberRegisterService 클래스 

@Component
public class MemberRegisterService {

 

MemberInfoPrinter 클래스 ( 속성값 = 빈의 이름 ) 

@Component("infoPrinter")
public class MemberInfoPrinter {

MemberListPrinter 클래스 ( 속성값 = 빈의 이름 )  

@Component("listPrinter")
public class MemberListPrinter {

 

@Component 애노테이션에 값을 주었는지에 따라 빈으로 등록할 때 사용할 이름이 결정 된다. 

애노테이션에 값을 주지 않게 되면 클래스 이름의 첫 글자를 소문자로 바꾼 이름을 빈 이름으로 사용한다.

 

 

2. @ComponentScan 애노테이션으로 스캔 설정

스프링 설정 클래스에 적용

 

@ComponentScan(basePackages = {"spring"}) // 속성 값 "spring"은 패키지 이름 

spring 패키지와 그 하위 패키지에 속한 클래스를 스캔 대상으로 설정 

package config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import spring.MemberPrinter;
import spring.MemberSummaryPrinter;
import spring.VersionPrinter;

@Configuration
@ComponentScan(basePackages = {"spring"})
public class AppCtx {

	@Bean
	@Qualifier("printer")
	public MemberPrinter memberPrinter1() {
		return new MemberPrinter();
	}
	
	@Bean
	@Qualifier("summaryPrinter")
	public MemberSummaryPrinter memberPrinter2() {
		return new MemberSummaryPrinter();
	}
	
	@Bean
	public VersionPrinter versionPrinter() {
		VersionPrinter versionPrinter = new VersionPrinter();
		versionPrinter.setMajorVersion(5);
		versionPrinter.setMinorVersion(0);
		return versionPrinter;
	}
}

 

 

 

3. 예제 실행

main클래스에서 일부 수정할 코드가 있는데 빈으로 검색하는 코드를 지워야됨

밑에 코드 "changePwdSvc" 제거 

	private static void processChangeCommand(String[] arg) {
		if (arg.length != 4) {
			printHelp();
			return;
		}
		ChangePasswordService changePwdSvc =
				ctx.getBean("changePwdSvc", ChangePasswordService.class);
		try {
			changePwdSvc.changePassword(arg[1], arg[2], arg[3]);
			System.out.println("암호를 변경했습니다.\n");
		} catch (MemberNotFoundException e) {
			System.out.println("존재하지 않는 이메일입니다.\n");
		} catch (WrongIdPasswordException e) {
			System.out.println("이메일과 암호가 일치하지 않습니다.\n");
		}
	}

 

밑에 코드 처럼 제거

	private static void processChangeCommand(String[] arg) {
		if (arg.length != 4) {
			printHelp();
			return;
		}
		ChangePasswordService changePwdSvc =
				ctx.getBean(ChangePasswordService.class);
		try {
			changePwdSvc.changePassword(arg[1], arg[2], arg[3]);
			System.out.println("암호를 변경했습니다.\n");
		} catch (MemberNotFoundException e) {
			System.out.println("존재하지 않는 이메일입니다.\n");
		} catch (WrongIdPasswordException e) {
			System.out.println("이메일과 암호가 일치하지 않습니다.\n");
		}
	}

 

 

 

 

 

 

 

오라클

 

빈값을 허락하지 않는 NOT  NULL

Not NULL은 특정 열에 데이터의 중복 여부와는 상관없이 NULL의 저장을 허용하지 않는 제약 조건이다. 반드시 열에 값이 존재해야만 하는 경우에 지정한다.열의 제약 조건으로 NOT NULL 지정 시 UPDATE문을 사용해서 ID나 Pwd에 NULL로 수정 불가

 

테이블을 생성할 때 NOT NULL 설정하기 

create table table_notnull(
    login_id VARCHAR2(20) not null,
    login_pwd VARCHAR2(20) not null,
    tel VARCHAR2(20)
);

 

 

제약 조건 이름 직접 지정

제약조건은 이름을 따로 지정해 주지 않으면 오라클에서 자동으로 이름이 지정됨 

실무에서 오라클이 자동으로 지정해 주는 이름이 제약 조건이 많아진 후 찾기 어려워질 수 있으므로 실무에서는

이름 붙이는 규칙을 정하여 제약 조건 이름을 직접 지정하는 경우가 많다.

 

테이블을 생성할 때 제약 조건에 이름 지정하기 

밑에 처럼 이름 지정 해주면 테이블이름_컬럼명_notnull 나중에 제약 조건이 뭔지 찾기 쉬움 

create table table_notnull2(
    login_id VARCHAR2(20) CONSTRAINT tblnn2_lgnid_nn not null,
    login_pwd VARCHAR2(20) CONSTRAINT tblnn2_lgnpw_nn not null,
    tel VARCHAR2(20)
);

 

 

 

 

 

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-08-03 55일차  (0) 2023.08.03
2023-08-02 54일차  (0) 2023.08.02
2023-07-31 52일차  (0) 2023.07.31
2023-07-28 51일차  (0) 2023.07.28
2023-07-27 50일차  (0) 2023.07.27

+ Recent posts