kenzi

스프링 3일차 본문

Spring

스프링 3일차

kenzi 2022. 3. 30. 08:54

백지로 따라가보기 

노마드 코더 자바스크립트 강의 듣기  --->포스팅 완료!

영어책 마저 읽기 

+ 스프링 문서 읽어보기 ........

 

 

 


스프링 정리 

 

 

setter injection 방식 

1. xml

<bean id = "authFailLogger" class = "ch02_obj.AuthFailLogger">
		<property name = "threshold" value = "2" />
</bean>

2. obj 

public class AuthFailLogger {
	
	//<property name = "threshold" value = "2" /> setter injection 
	private int threshold;
	public void setThreshold(int threshold) {
		this.threshold = threshold;
		
	}

}

xml에서 value = "2"가 obj에서 int threshold로 들어가는 것 

변수명은 내맘대로 정하는 것 

 

 

 

 

 

 

https://jayviii.tistory.com/10

 

설정을 더 간결하게, context:component-scan

스프링에서의 역할 분담, WebApplicationContext와 연관된 글. 그저 좋다는 말에.. 한창 스프링을 배우기 시작할 무렵에 복잡한 XML 설정을 자바 애노테이션 기반으로 간단하게 하겠다고 의미도 모른 채

jayviii.tistory.com

 

 

스프링 프레임워크 공식 문서 

https://docs.spring.io/spring-framework/docs/5.2.19.RELEASE/spring-framework-reference/core.html#spring-core

 

Core Technologies

In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do

docs.spring.io

 

 

 

 

 

 

 

 

xml에서 context:component-scan으로 가져오는 방법 

1) Container4_scan.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
	xmlns:context = "http://www.springframework.org/schema/context"
	xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!-- scan으로 객체를 가져오겟다 -->
	<context:component-scan base-package="ch02_objScan"/>
	
	
	
	
	<bean id = "user1" class = "ch02_obj.User">
	<constructor-arg value = "kicuser"></constructor-arg>
	<constructor-arg value = "1111"></constructor-arg>
	</bean>
	
	
	
	<bean id = "user2" class = "ch02_obj.User">
	<constructor-arg value = "kicstu"></constructor-arg>
	<constructor-arg value = "1234"></constructor-arg>
	</bean>
	
	
	<bean id = "authFailLogger" class = "ch02_obj.AuthFailLogger">
		<property name = "threshold" value = "2" />
	</bean>
	
	
</beans>

1-1) base-package인 패키지안에 클래스들에 @Component 쓰기

 

AuthenticationService.java

@Component //ch02_objScan에 있는 객체를 component-scan으로 자동으로 가져옵니다
public class AuthenticationService {
	
	@Autowired //프로퍼티를 자동으로 연결해줍니다
	UserRepository userRepository;
	
	@Autowired
	AuthFailLogger authFailLogger;
	
	/*
	Autowired에 의해서 자동으로 연결해주니까 이 과정이 필요없습니다
	//setter injection 방식
	public void setUserRepository(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
	
	//setter injection 방식
	public void setAuthFailLogger(AuthFailLogger authFailLogger) {
		this.authFailLogger = authFailLogger;
	}
	*/
	public void authenticate(String userId, String password) {
		User user = userRepository.findUserById(userId); //아이디 확인
		
		if(user == null) {
			throw new UserNotFoundException();			
		}
		if(!user.getPassword().equals(password)) {
			System.out.println("login 불가합니다");
			
			authFailLogger.insertBadPw(userId, password);
								
		} else {
			System.out.println("login이 되었습니다");
		}
		
		
		System.out.println(userId + " : " + password);
	}
	
	
}

 

 

PasswordChangeService.java

xml에서의 코드

<bean id = "pwChangeSvc" class = "ch02_obj.PasswordChangeService">
		<constructor-arg>
			<ref bean = "userRepository"></ref>
		</constructor-arg>
</bean>

위 코드를 클래스에 @Component(id명) 과 @Autowired 방식으로 Bean을 생성할 수 있습니다

*@Component에 id를 따로 적지 않으면 자동으로 맨 첫 글자를 소문자로 바꿔서 찾습니다

PasswordChangeService.java

@Component("pwChangeSvc")
public class PasswordChangeService {
	
	UserRepository userRepository;
	
	@Autowired
	public PasswordChangeService(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
	
	
	public void changePassword(String userId, String oldPw, String newPw) {
		User user = userRepository.findUserById(userId);
		System.out.println("old:" +user);
		if(user == null)
			throw new UserNotFoundException();
		if(user.getPassword().equals(oldPw))
		{	user.setPassword(newPw);
		System.out.println("new:" +user); }
		else
		{	throw new IllegalArgumentException("illegal password");}
		
		
		
	}
	
	

} //end class

 

UserRepository.java

@Component
public class UserRepository {

	//<property name = "users"> : setter injection
	
	private Map<String, User> map = new HashMap<>();
	
	@Autowired
	public void setUsers(List<User> li) {
		for(User u : li) {
			map.put(u.getId(), u);
			System.out.println(u);
		}
		
	}
	
	
	public User findUserById(String id) {
		
		return map.get(id);
		
		
	}
	
	
} //end class

여기서 xml에 있는 bean 친구들도 package밑으로 따로 빼서 클래스에 @Component 사용하면 안되나요?

가능하긴 합니다만 value 값을 지정해준 객체라서 클래스를 따로 만들어 @Component를 쓰면 

나중에 값을 바꿀때 클래스로 가서 값을 별도로 수정해야합니다

xml으로 빼놓으면 관리하기가 쉬운데 굳이 그럴 필요가 있을까요? 

 

 

 

 

 

xml을 쓰지 않고 Configuration방식 

xml을 사용하지 않고 java클래스에서 @어노테이션만으로 bean 생성 

1) Main5_Anno.java 에서 

factory = new GenericXmlApplicationContext(xml명.xml); 

=> factory = newAnnotationConfigApplicationContext(xml 대신 사용할 자바클래스.class); 사용해줍니다

 

public class Main5_Anno {

	static AnnotationConfigApplicationContext factory;
	
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		factory = new AnnotationConfigApplicationContext(Container3_Anno.class);
		
		
		//getBean하는 방식 중에 이런 방식도 있습니다
		PasswordChangeService pcw = (PasswordChangeService) factory.getBean("pwChangeSvc");
		//System.out.println(pcw);   //확인
		//System.out.println("ok");  //확인
		
		pcw.changePassword("kicuser","1111","2222");
	
		AuthenticationService authSvc = 
				factory.getBean("authenticationService",AuthenticationService.class);
		runAuthAndCatchAuthEx(authSvc,"kicuser","1111");
		runAuthAndCatchAuthEx(authSvc,"kicuser","11111");
		runAuthAndCatchAuthEx(authSvc,"kicuser","111111");
		
		
		
		System.out.println("ok");
		
		
	} // end main

		private static void runAuthAndCatchAuthEx (
				AuthenticationService authSvc, String userId, String password) {
			try {
			authSvc.authenticate(userId, password);
			} catch(Exception ex) {
				
			}
		}
	
	
} //end class

 

Container3_Anno.class에서 

1-1) @configuration @Bean을 사용해줍니다 

@Configuration
public class Container3_Anno {
	
	
	@Bean
	//public xml에서의 class, id ()    
	public User user1() {
		return ~~~~
	}
	
	@Bean
	public User user2() {
		return ~~~
	}
	
	
	@Bean
	public AuthenticationService authenticationService() {
		AuthenticationService a = new AuthenticationService();
		a.setUserRepository(userRepository());
		a.setAuthFailLogger(authFailLogger());
		return a;
		
	}
	
	
	@Bean
	public UserRepository userRepository() {
		UserRepository u = new UserRepository();
		u.setUsers(Arrays.asList(user1(),user2()));
		return u;
	}
	

	@Bean
	public AuthFailLogger authFailLogger() {
		AuthFailLogger auth = new AuthFailLogger();
		auth.setThreshold(2);
		return auth;
	}
	
	
	@Bean("pwChangeSvc")
	public PasswordChangeService pwChangeSvc() {
		return new PasswordChangeService(userRepository());
	}
	
	
} //end class

 

 

 

2. configuration 과 component의 차이

component-scan은 xml이 있고 컨테이너 리소스는 xml인데 클래스에 @component 줘서 Bean이 여기 있어 이거 스캔할거야라는 의미 

configuration은 xml이 없어서 configuration이 컨테이너 리소스자체를 의미하고 Bean은 @bean으로 생성 

 

1) xml & component-scan & @Component로 컨테이너 생성후 빈을 연결하는 방식 

2) xml 없이 & @Configuration & @Bean을 연결하는 방식 

둘 중에 선택해서 사용하면 된다 

 

 

 

 

3. autowired는 어디에 거는가? 

여러가지 방식이 있는데 어디에 걸어도 딱히 상관은 없다 

다만 여러군데에 동시다발적으로 걸어서는 안된다 

1) 필드에 걸기 

    @Autowired //프로퍼티를 자동으로 연결해줍니다
	UserRepository userRepository;
	
	@Autowired
	AuthFailLogger authFailLogger;

2) 생성자에 걸기

UserRepository userRepository;
	
	@Autowired
	public PasswordChangeService(UserRepository userRepository) {
		this.userRepository = userRepository;
	}

 

3) setter에 걸기 

private Map<String, User> map = new HashMap<>();
	
	@Autowired
	public void setUsers(List<User> li) {
		for(User u : li) {
			map.put(u.getId(), u);
			System.out.println(u);
		}
		
	}

 

 

스프링은 크게 1) 컨테이너인가?-2가지 방식 2) 빈인가?-3가지 방식 3) auto-wired는 어디있지? - 아직 수업진행중


 

 

1. 컴파일러 언어? 인터프리터 언어?  -----> 새로 포스팅 완료!

2. 포트란 무엇인가? ----> 오늘 스프링을 다시 정리해야하기 때문에 내일의 할일로 ....

 

'Spring' 카테고리의 다른 글

스프링 4일차 정리  (0) 2022.03.31
스프링은 3가지로 끝난다  (0) 2022.03.31
컨테이너와 빈 방식에 관하여  (0) 2022.03.30
스프링 2일  (0) 2022.03.29
스프링 기초 복습 ( feat 빈 설정방법)  (0) 2022.03.28
Comments