일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Shell code
- 웹해킹
- webhacking.kr
- 워게임
- Spring MVC
- Payload
- Spring
- webhacking
- BOF
- 운영체제
- 정보보안기사
- pwnable
- hacking
- LOB
- PWN
- OS
- wargame
- 해킹
- Pwnable.kr
- System
- stack overflow
- Lord of BOF
- Operating System
- 정보보안기사 실기
- system hacking
- Spring Framework
- 네트워크
- Buffer Overflow
- 정보처리기사 실기
- SQL
- Today
- Total
DongDD's IT
[Spring] Dependency Injection(DI) 본문
[Spring] Dependency Injection(DI)
Dependency Injection
DI 배경
- 컴포넌트를 생성자에서 직접 생성하는 방식 —> 생성한 클래스를 교체하는 것이 어려움
→ 클래스의 결합도가 높음
→ 클래스의 결합도를 낮추기 위해 생성자의 인수로 컴포넌트를 넘기고 초기화하는 방식이 있음
- 이러한 방식으로 클래스의 결합도를 낮추더라도 변경이 발생하는 경우 재작업을 피할 수 없음
→ 외부에서 컴포넌트를 생성하고 내부에서 사용 가능하게 해주는 DI(Injection) 개념 나옴
→ DI를 자동으로 처리하는 기반을 DI Container라고 부름
DI 장점
- 의존성 해결
- 인스턴스의 scope 관리
- AOP 기능 추가
IoC(Inversion of Control)
- 인스턴스 관리를 DI Container가 해줌(제어가 역전되었다고 표현)
DI Container
ApplicationContext
- Spring Framework에서의 DI Container
1 2 3 | ApplicationContext applicationContext = new AnnotationConfigApplicationContext( AppConfig.class); applicationContext.getBean(aa.class); | cs |
- AppConfig에 @Configuration과 @Bean을 사용해 bean 정의
- getBean을 이용해 Bean을 불러와 사용
- Look up : DI Container가 Bean을 찾는 작업
Bean 설정 방법
1. 자바 기반 설정
- @Configuration과 @Bean을 사용하여 설정
2. XML 기반 설정
3. Annotation 기반 설정
- @Component 등을 사용하여 설정
- ComponentScan : DI Container가 Component를 탐색하는 과정 (@ComponentScan("com.example.prj"), default = 설정 클래스가 들어있는 패키지 이하)
- Autowiring : DI 컨테이너가 자동으로 필요로 하는 의존 컴포넌트 주입(@Autowired)
의존성 주입 - 1
1. 설정자 기반 의존성 주입(Setter-based dependency injection)
1) 자바 기반 세터 인젝션
1 2 3 4 5 6 7 | @Bean TestBean testBean() { TestBeanImpl testBean = new TestBeanImpl(); testBean.setTestBean1(testBean1()); testBean.setTestBean2(testBean2()); return testBean; } | cs |
2) 자바 기반 매개변수 세터 인젝션
1 2 3 4 5 6 7 | @Bean TestBean testBean(TestBean1 testBean1, TestBean2 testBean2) { TestBeanImpl testBean = new TestBeanImpl(); testBean.setTestBean1(testBean1()); testBean.setTestBean2(testBean2()); return testBean; } | cs |
3) 어노테이션 기반 세터 인젝션
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Component public class TestBeanImpl implements TestBean { private TestBean1 testBean1; private TestBean2 testBean2; @Autowired public void setTestBean1(TestBean1 testBean1) { this.testBean1 = testBean1; } @Autowired public void setTestBean2(TestBean2 testBean2) { this.testBean2 = testBean2; } } | cs |
2. 생성자 기반 의존성 주입(Constructor-based dependency injection)
1) 어노테이션 기반 컨스트럭터 인젝션
1 2 3 | @ConstructorProperties({"testBean1", "testBean2"}) public TestBeanImpl(TestBean1 testBean1, TestBean2 testBean2) { } | cs |
3. 필드 기반 의존성 주입(Field-based dependency injection)
- 생성자나 설정자 method를 사용하지 않고 DI Container를 통해 의존성을 주입하는 방식
- @Autowired 사용
1) 어노테이션 기반 필드 인젝션
1 2 3 4 5 6 7 8 9 10 11 | @Component public class TestBeanImpl implements TestBean { @Autowired TestBean1 testBean1; @Autowired TestBean2 testBean2; } | cs |
- Autowiring : @Bean이나 XML을 사용하지 않고 자동으로 주입
의존성 주입 - 2
1. Type 기반 → setter, constructor, field injection 사용 가능
- Bean을 찾지 못하는 경우, NoSuchBeanDefinitionException 발생(@Bean(required=null) 사용 → null)
- 같은 타입의 여러 Bean 존재할 경우, NoUniqueBeanDefinitionException
→ @Bean(name=""), @Qualifer("name") 사용
→ @Primary : 우선적으로 선택될 bean 설정
- Qualifier를 Annotation으로 구현
어노테이션 구현
1 2 3 4 5 6 7 | @Target({ElementType.FIELD, ElementType.CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Qualifier public @interface TestAnnotation { } | cs |
- @Target : 어노테이션 적용 위치 결정
- @Retention : 어노테이션 적용 범위(어떤 시점까지 적용할지)
- @Documented : 문서에도 어노테이션 정보 표시
- @Inherited : 자식 클래스가 어노테이션 상속 받을 수 있음
2. Name 기반 → setter, field injection 사용 가능
- @Resource(name="") 사용
→ name이 없을 경우, 변수명이 name으로 지정
→ 해당 name이 없을 경우, type 기반으로 autowiring 시도
Component Scan
- Class Loader 스캔 → 클래스 발견 → DI Container에 등록
1. 기본 설정 컴포넌트 스캔
- Annotation이 붙은 클래스가 탐색 태상
- @ComponentScan(basePackages = "package"), @ComponentScan(basePackages = "package")
- 탐색 범위가 넓고 처리하는 시간이 길기 때문에 적절한 범위가 필요
2. 필터 적용 컴포넌트 스캔
- @ComponentScan(includeFilters ={ })
- useDefaultFilters = false : 기본 스캔 대상 제외
- excludeFilters={} : @Exclude 어노테이션이 설정된 컴포넌트를 제외
Bean Scope
- DI Container가 bean scope 관리
- DI Container가 관리하는 default scope는 single tone
1. Scope 종류
- singleton
- prototype
- request
- session
- globalSession
- application
- custom
-> @Bean, @Component 밑에 @Scope("type")로 Scope 설정
2. 서로 다른 bean scope 주입
- prototype의 bean을 singleton bean으로 주입할 경우, singleton으로 취급
- Lookup method injection으로 해결(prototype)
- DI Container가 bean을 lookup하는 메소드를 만들고 메소드를 의존할 bean에게 주입
- @Lookup annotation 이용
1) Lookup method injection
1 2 3 4 5 6 7 8 9 10 11 | @Component public class TestBeanImpl implements TestBean { public void test() { ProtoBean protoBean = protoBean(); } @Lookup ProtoBean protoBean() { return null; } } | cs |
- value 속성에 bean 이름 지정(없을 경우, 메소드의 반환 값 타입을 보고 룩업 빈 결정)
2) Scoped Proxy(request, session scope, globalSession)
- prototype은 효율성 측면에서 lookup method injection 사용
- Bean을 proxy로 감싸고, proxy를 다른 bean에 주입, 주입된 bean에서 proxy 메소드를 호출하면 proxy 내부적으로 bean을 lookup하고 메소드 수행
- @Scope(proxyModes = '')
- proxyModes
- ScopedProxyMode.INTERFACES : 인터페이스 기반 proxy
- ScopedProxyMode.TARGET_CLASS : 서브클래스 기반 proxy
3. Custom Scope
- 사용자가 직접 정의하여 scope 사용
1 2 3 4 5 6 | @Bean static CustomScopeConfigurer customScopeConfigurer() { CustomScopeConfigurer configurer = new CustomScopeConfigurer(); configurer.add("thread", new SimpleThreadScope()); return configurer; } | cs |
- @Scope("thread")로 사용
Bean
Bean 생명주기
1. 초기화
- Bean 설정
- DI
- 생성 후 처리(@PostConstruct)
2. 사용
3. 종료
- 전처리(@PreDestroy, @Bean(destoryMethod="method_name")
Bean Config 분할
- @Import를 통해 AConfig에서 BConfig, CConfig를 import하여 config 정의
Profile 별 Config
- phase : (test1, test2), test3, test4
1. 자바 기반 Configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Java-based Configuration // @Configuration @Profile({"test1","test2"}) public class test1Config { //config } @Configuration @Profile({"test3") public class test3Config { } @Configuration @Profile({"test4") public class test4Config { } | cs |
2. application.yml Configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // application.yml file // --- spring: profiles: test1, test2 //test1, test2 config --- spring: profiles: test3 //test3 config --- spring: profiles: test4 //test4 config --- | cs |
3. 여러 개의 properties 파일 생성
- application-test1.properties
- application-test2.properties
- application-test3.properties
- application-test4.properties
-> application-${spring.profiles.active}.properties로 지정
- Spring Boot의 경우, edit configurations.. 에서 Active profiles 설정
- Tomcat의 경우, VM options에 "-Dspring.profiles.active=test"와 같은 옵션을 주어 실행(또는 환경변수 설정)
'프로그래밍 > Spring' 카테고리의 다른 글
[Spring] Spring Web Application, Controller, Exception Handler (0) | 2019.04.02 |
---|---|
[Spring] Spring MVC - MVC, IntelliJ 설정, 프로젝트 생성 (0) | 2019.03.28 |
[Spring] Datasource, Spring JDBC, Transaction (0) | 2019.03.27 |
[Spring] Aspect of Programming(AOP), Resource (0) | 2019.03.20 |
[Spring] Spring Framework 개요 (0) | 2019.03.18 |