kenzi
스프링 3일차 본문
백지로 따라가보기
노마드 코더 자바스크립트 강의 듣기 --->포스팅 완료!
영어책 마저 읽기
+ 스프링 문서 읽어보기 ........
스프링 정리
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
스프링 프레임워크 공식 문서
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 |