개발자 끄적끄적

DI(Dependency Injection) 본문

웹프레임워크

DI(Dependency Injection)

햏치 2024. 4. 23. 12:43

<Spring Bean>
- Spring의 DI Container에 의해 관리되는 POJO(Plain Old Java Object)를 Bean이라 부른다
- POFO는 Spring 애플리케이션을 구성하는 핵심 객체
- Spring Ioc Container 또는 DI 컨테이너에 의해 생성 및 관리




<@Bean>
- 메소드 레벨에서 선언하며, 반환되는 객체(인스턴스)를 개발자가 수동으로 빈으로 등록
- 메소드에서 사용, 즉 메소드 이름으로 빈 이름이 결정
- 개발자가 컨트롤이 불가능한 외부 라이으버리 사용 시 사용

- ex)
@Configuration
public class AppConfig{
@Bean
public MemberService memberService(){
  return new MemverServiceImpl();
}
}


<@Component>
- 클래스 레벨에서 선언하며, 스프링이 런타임시에 컴포넌트스캔을 하여 자동으로 빈을 찾고
  등록하는 애노테이션
- 클래스에 사용
- 개발자가 직접 컨트롤이 가능한 내부 클래스에 사용
- ex)
@Component
public class Utility{
...
}



<@Configuration>
- 설정할 클래스
- @Bean을 사용하는 클래스에는 반드시 @Configuration 어노테이션을 활용하여
  해당 클래스에서 Bean을 등록하고자 함을 명시
- @Bean 어노테이션은 반드시 @Configuration과 함께 사용




<@Autowired>
- 스프링 컨테이너에 등록한 빈에게 의존 관계 주입이 필요할 때, DI(의존성 주입)을 도와주는 어노테이션
- @Autowired 어노테이션이 부여된 메서드가 실행되며 필요한 인스턴스를 주입
- @Autowired는 총 3가지 방법으로 실현 가능
  1. 생성자
  2. 수정자(setter)
  3. 필드 사용가능
- 생성자가 하나일 경우 @Autowired를 생략 가능



<DI>
- 결합도가 낮다 
- ex)
@Component //자동으로 빈 등록
public class PersonService {
    private Person person;

    @Autowired
    public PersonService(Person person) {
        this.person = person;
    }

    public void printPerson() {
        System.out.println("Name: " + person.getName() + 
", Age: " + person.getAge());
    }
}




<AOP(Aspect-Orientd Programming>
- 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 
  각각 모듈화 하겠다는 것
- 모듈화 : 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것
- 스프링 @AOP를 사용하기 위해서 다음과 같은 의존성 추가
  - ex)
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

- ex)
public class UserService {
    public void addUser(User user) {
        // Add the user to the database
     }
}
//We want to log information about when the addUser method is called  

  - Non-AOP Approach
  - ex)
public class UserService {
    public void addUser(User user) {
        // Log information about adding the user
        System.out.println("Adding user: " + user.getUsername());
        
        // Add the user to the database
    }
}
----------------------------------------------------------------------

  - AOP Approach
  - ex)
@Aspect
public class LoggingAspect {

    @Before("execution(* kr.ac.hansung.UserService.addUser(..)) && args(user)")
    public void logBefore(JoinPoint joinPoint, User user) {
        System.out.println("Adding user: " + user.getUsername());
    }

}
  - @Aspect는 포인트컷(Pointcut)과 어드바이스(Advise)로 구성된 어드바이저(Advisor)의 생성을 편리하게 해주는 기능을 가진 어노테이션

<용어 이해>
- Aspcet : 공통적인 기능들을 모듈화
- Target : Aspect가 적용될 대상을 의미하며 메소드, 클래스 등이 이에 해당
- Join Point : Aspect가 적용될 수 있는 시점을 의미하며 메솓 실행 전, 후 등이 될 수 있다
- Advice : Aspcet의 기능을 정의한 것으로 메서드의 실행 전,후,예외처리 발생 시 실행되는 코드
- Point cut : Advice를 적용할 메소드의 범위 지정




<주요 어노테이션>
- @Aspcet : 해당 클래스를 Aspect로 사용
- @Before : 대상 "메서드"가 실행되기 전에 Advice 실행
- @AfterReturning : 대상 "메서드"가 정상적으로 실행되고 반환된 후에 Advice를 실행
- @AfterThrowing : 대상 "메서드에서 예외가 발생"했을 때 Advice를 실행
- @After : 대상 "메서드"가 실행된 후에 Advice를 실행
- @Around : 대상 "메서드" 실행 전,후 또는 예외 발생 시에 Advice를 실행




<PSA(Portable Service Abstraction)>
- 환경의 변화와 관계 없이 일관된 방식의 기술로서의 접근 환경을 제공하는 추상화 구조
- PSA = 잘 만든 인터페이스




<Object Depenencies>
- ex)
public class PetOwner{
    private AnimalType animal;

    public PetOwner() {
     this.animal = new Dog();
    }    
}
- tight couping





<DI>
- ex)
public class PetOwner{
    private AnimalType animal;

    public PetOwner(AnimalType animal) {
     this.animal = animal;
    }    
}
----------------------------------------------------------------------
- Spring Container : Create the AnimalType object(Dog, Cat)
  1) Dog
public class Dog 
implements AnimalType{
    //…
}
----------------------------------------------------------------------
  2) Cat
public class Cat 
implements AnimalType{
    //…
}




<The Spring Container>
- The configuration metadata can be represented either by 
  - XML
  - Java annotations
  - Java-based Configuration


- Spring comes with two types of containers
  - BeanFactory
  - ApplicationContext




<Spring Bean Definintion>
- XML based configuration file
<!-- A simple bean definition -->
<bean id="..." class="...">
</bean>

<!-- A bean definition with scope-->
<bean id="..." class="..." scope="singleton">
</bean>

<!-- A bean definition with property -->
<bean id="..." class="...">
<property name="message" value="Hello World!"/>
</bean>

<!-- A bean definition with initialization method -->
<bean id="..." class="..." init-method="...“ >
</bean>




<Spring Bean의 구성요소>
- Class : Bean으로 등록할 JAVA 클래스
- id : Bean의 고유 식별자
- scope : Bean을 생성하기 위한 방법(ex. singleton, prototype 등)
- constructor-arg : Bean 생성 시 생성자에 전달할 파라미터
- property : Bean 생성 시 setter에 전달할 인수




<Spring Bean Scope>
- singletone : Single instace of bean in every getBean() call [default]
  - A ‘singleton’ bean is created once in the Spring container.
    This ‘singleton’ bean is given every time when referred. 
    It is garbage collected when the container shuts down

- prototype : New instance of bean in every getBean() call
  - A ‘prototype’ bean means a new object in every request.
    It is garbage collected in the normal way, i.e., 
   when there is no reference for this object

- request : Single instance of bean per HTTP request
- session : Single instance of bean per HTTP session
- global-session : Single instance of bean per global HTTP session
*requst, session, global-session : Valid in the context of web-aware 'ApplicationContext'




<Dependency Injection Methods>
- Constructor-based Injection : Pass dependencies in via 'constructor'
  - ex)
<bean id="petOwner" class="kr.ac.hansung.spring.PetOwner" >
    <constructor-arg    ref ="dog" />
</bean>
----------------------------------------------------------------------
public class PetOwner {

    public AnimalType animal;

    public PetOwner(AnimalType animal) {
this.animal = animal;
    }
    …
}




- Setter-based Injection : Pass dependencies in via property setters
- ex)
<bean id="petOwner" class="kr.ac.hansung.spring.PetOwner">
    <property name="animal" ref="dog" />
</bean>
----------------------------------------------------------------------
public class PetOwner {

    public AnimalType animal;

    public void setAnimal(AnimalType animal) {
this.animal = animal;
    }

    …
}




<@Required>
- 반드시 주입해야 할 property를 설정해주는 어노테이션
- POJO 클래스의 setter 메소드에 @Required를 설정해주면 필드 데이터는 null이면 안되고,
  무조건 setter를 이용하여 값을 주입해주어야한다



<@Qualifier>
- 빈은 추가 구분자를 붙여주는 방법으로 생성자에서 해당 구분자를 명시하면 그 구분자를 가진 빈을 명시



<@Autowired와 @Resource의 차이점>
- @Autowired : 클래스로 Bean을 지정(생성자/필드/메서드에 모두 적용 가능)
- @Resource : Name으로 Bean을 지정(필드/메서드에서만 적용 가능)
*@Autowired 어노테이션 타입을 이용해서 의존성을 주입한다면,
 @Resource는 빈 이름을 사용해서 의존성을 주입한다
-  ex) sqlSession은 SqlSessionTemplate 클래스에 의존성을 가지게 된다
@Repository
public class CommonDao {
    @Autowired
    private SqlSessionTemplate sqlSession;
}

- ex)sqlSession은 BlueSqlSessionTemplate의 이름을 가진 Bean 객체에 의존성을 가지게 된다
@Repository
public class TestDao {
    @Resource(name="BlueSqlSessionTemplate")
    private SqlSessionTemplate sqlSession;
 }

'웹프레임워크' 카테고리의 다른 글

Spring WebForm  (0) 2024.04.23
Spring MVC  (0) 2024.04.23
Dependecy Injection, Spring Annotation  (0) 2024.03.13