## 54. IoC 컨테이너 적용하기
- IoC 컨테이너의 구동 원리와 구현
- 리스너 객체를 IoC 컨테이너로 관리하기
ApplicatioinContext.java
ㄴ DispatcherListener 클래스에 있는 해당 코드 복사해와서 붙여넣기
ApplicatioinContext.java
ㄴ 생성자 추가
ㄴ configClass는 Class<?> 타입으로 전달됨
ApplicatioinContext.java
ㄴ java.lang.reflect.Method 이용
ApplicatioinContext.java
ㄴ methods 이름 출력하도록 함
ApplicatioinContext.java
=>
ㄴ BoardAddListener 클래스에 어떤 메서드가 정의되어있는지 메서드 목록가져오기
=> service 메서드만 존재함
ApplicatioinContext.java
ㄴ 클래스의 기본 생성자를 알아내도록 함
ApplicatioinContext.java
ㄴ 기본 생성자를 이용하여 객체를 생성하도록 함
ApplicatioinContext.java
ㄴ 해당 코드 아래쪽으로 이동시켜줌
ApplicatioinContext.java
ㄴ invoke(Object obj) 메서드는 Method 객체가 나타내는 메서드를 호출함
ㄴ obj는 메서드를 호출할 객체를 의미함
ㄴ obj 객체에 속한 메서드인 m을 호출하는 것
ㄴ 만약 메서드가 매개변수를 가지는 경우, 적절한 인자를 invoke() 메서드로 전달하여 호출할 수 있음
ㄴ 리턴 값을 메서드 이름으로 빈 컨테이너에 저장하도록 함
ㄴ bitcamp.report.config 패키지 생성
ㄴ bitcamp.report.config 패키지에 AppConfig 라는 이름의 클래스 생성
AppConfig .java
ㄴ SqlSessionFactory 객체를 생성하여 반환하는 메서드인 createSqlSessionFactory()를 정의
ㄴ mybatis-config.xml 설정 파일을 이용하여 SqlSessionFactory 객체를 생성하고, 이렇게 생성된 SqlSessionFactory 객체를 SqlSessionFactoryProxy를 사용하여 감싸서 반환하도록 함
ㄴ mybatis 준비 (DispatcherListener.java 에서 가져옴)
ApplicationContext .java
ㄴ beanContainer 에서 값을 꺼내오는 getBean 메서드 생성
ApplicationContext .java
ㄴ 메서드의 리턴 타입이 없다면 무시하도록 함 (continue)
ApplicationContext .java
=>
=>
ㄴ 모두 같은 의미
ㄴ beanContainer에 저장된 객체들의 이름(키)을 String 배열로 반환하는 메서드인 getBeanNames()를 생성
ApplicationContext .java
ㄴ ApplicationContext 객체를 생성하고 AppConfig 클래스를 사용하여 설정 정보를 제공하도록 함
Annotaion 생성
ㄴ Bean 이라는 이름의 Annotaion 생성
AppConfig.java
ㄴ @Bean 애노테이션 추가
Bean.java
ㄴ Bean 애노테이션 설정
ApplicationContext.java
ㄴ @Bean 애노테이션을 붙이지 않았다면 무시하도록 함
ApplicationContext.java
=>
ㄴ AppConfig 클래스에서 설정한 빈들의 이름이 출력됨
AppConfig.java
ㄴ @Bean 을 모두 입력할 경우 모두 출력됨을 확인할 수 있음
AppConfig.java
ㄴ @Bean 을 입력하지 않으면 출력되지 않은 것을 확인할 수 있음
AppConfig.java
ㄴ @Bean 을 입력한 createSqlSessionFactory 만 출력됨을 확인할 수 있음
AppConfig.java
ㄴ 타입을 void 로 변경할 경우 @Bean 을 입력해도 출력되지 않음을 확인 (타입이 인터페이스여야만 함)
Bean.java
ㄴ @Bean 애노테이션에 value(), value2(), ok() 를 정의
=>
AppConfig.java
ㄴ @Bean 애노테이션에 String 타입의 value(), String 타입의 value2(), int 타입의 ok() 가 정의되어있으므로 @Bean 선언 시 해당 값도 괄호 안에 적어줘야 함
Bean.java
=>
AppConfig.java
ㄴ @Bean 애노테이션에 value 값이 default 가 "" 으로 정의되어있으므로 @Bean 만 적어줘도 됨
ApplicationContext.java
=>
AppConfig.java
=>
ㄴ @Bean 애노테이션에 객체 이름이 지정되어 있다면 그 이름으로 객체를 저장함
ㄴ 애노테이션에 설정된 이름이 없다면 메서드 이름을 사용하여 객체를 저장함
AppConfig.java
ㄴ createSqlSessionFactory -> SqlSessionFactory 로 변경
Bean.java
ㄴ @Target 애노테이션을 이용하여 @Bean 애노테이션은 메서드 타입에만 붙일 것을 정의
=>
Bean.java
ㄴ 배열의 값이 한 개이므로 중괄호 제거해도 됨
=>
Bean.java
Bean.java
ㄴ value 는 생략해도 됨
=>
AppConfig.java
ㄴ 이렇게 클래스 위에 붙일 경우 오류 발생함을 확인
AppConfig.java
ㄴ @ComponentScan 이라는 애노테이션을 선언하도록 함
ComponentScan.java
ㄴ ComponentScan 이라는 이름의 애노테이션을 생성
=>
ComponentScan.java
ㄴ 해당 애노테이션을 추가
AppConfig.java
ㄴ ComponentScan 애노테이션이 String 배열로 이루어진 basePackages 가 필수 값이므로 value -> basePackages 로 변경해주기
=>
AppConfig.java
ㄴ 중괄호 생략해줘도됨
ApplicationContext.java
ㄴ 해당 코드 모두 잘라내기
=>
ApplicationContext.java
ㄴ processBeanAnnotation 메서드 안에 붙여넣기
ApplicationContext.java
ㄴ ApplicationContext 클래스의 생성자에서 설정 정보를 담은 클래스인 configClass 를 통해 AppConfig 클래스가 전달되도록 하고, processBeanAnnotation 메서드를 호출하여 설정 클래스에서 @Bean 애노테이션이 붙은 메서드들을 찾고, 해당 메서드들을 실행하여 리턴하는 객체들을 빈 컨테이너에 등록하도록 함
ApplicationContext.java
ㄴ processComponentScanAnnotation 이라는 이름의 메서드를 사용하도록 선언한 후 create method 'processComponentScanAnnotation(Class<?>)' 를 선택하여 해당 메서드 생성
ApplicationContext.java
ㄴ configClass에서 @ComponentScan 애노테이션을 찾고, 해당 애노테이션에 설정된 정보를 처리하도록 함
ApplicationContext.java
ㄴ componentScan 이 null 이 아니라면 processComponentScanAnnotation(componentScan) 를 호출하도록 함
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
ㄴ "." 이라고 문자열 내에서 .은 정규표현식에서 특수문자로 취급되므로 [] 를 추가해줌
=>
ApplicationContext.java
=>
ApplicationContext.java
ㄴ 값이 잘 넘어가는지 확인하기 위해 System.out.println 으로 출력해보기
=>
AppConfig.java
=>
ㄴ handler 패키지도 . -> / 으로 잘 변경됨을 확인
basePackage.replaceAll(".", "/") => 이렇게 할 경우 아래와 같이 출력되므로 basePackage.replaceAll("[.]", "/") 이렇게 해야됨
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
ㄴ 출력 구분하기 위해 구분선을 출력해주기
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
ㄴ .class 로 끝나는 파일만 출력하도록 함
=>
ApplicationContext.java
ㄴ dirInputStream이 null인지 확인하여 디렉토리 정보를 읽을 수 없는 경우, 즉 해당 패키지 경로에 대한 리소스가 존재하지 않는 경우에는 이후 작업을 중단하고 메서드를 종료하도록 함
ApplicationContext.java
ㄴ basePackage 인 bitcamp.report.dao 와 bitcamp.report.handler 를 합쳐서 풀네임을 만들어줌
=>
ApplicationContext.java
ㄴ HashSet 을 이용하여 classes 에 .class로 끝나는 모든 클래스 파일들의 경로를 중복 제거하여 저장하도록 함
ApplicationContext.java
ㄴ for 문을 이용하여 저장된 className 을 출력해보도록 함
=>
=>
ApplicationContext.java
ApplicationContext.java
=>
=>
ApplicationContext.java
ㄴ .class 를 모두 빈 문자열로 변경해주기
=>
ApplicationContext.java
=>
ApplicationContext.java
ㄴ line 보다는 filename 이 더 직관적이므로 변수명 변경
ApplicationContext.java
ㄴ 전통적인 컬렉션 데이터 처리 방식 주석 처리
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
=>
ApplicationContext.java
ㄴ 클래스 로딩하다가 예외가 발생하면 무시하도록 예외처리
=>
ApplicationContext.java
ㄴ 스트림 프로그래밍 방식 주석 처리
ApplicationContext.java
=>
ㄴ 람다 처리
=>
ㄴ 출력 확인
다음 내용은 이어서 계속,,
https://la-reveuse.tistory.com/235