Controller,Service,Repository에서의 DI

2023. 11. 5. 03:32백엔드/Spring Boot

🤔 Controller,Service,Repository에서 @Autowired를 이용하여 DI를 할 수 있는 이유에 대하여 알아보자. 

 

* 예시 코드 

1. Controller

package com.example.demo.controller;

import com.example.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController // @RestController > @Controller > @Component 를 포함하고 있어 DemoController 가 빈으로 등록됨
public class DemoController {

    @Autowired // DI 주입 요청
    DemoService demoService; // 생성자 주입

    @RequestMapping("/test")
    public String test() {
        return demoService.find();
    }
}

 

2. Service

package com.example.demo.service;

import com.example.demo.repository.DemoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DemoService {
    @Autowired
    DemoRepository demoRepository;

    public String find() {
        return demoRepository.find();
    }
}

 

3. Repository

package com.example.demo.repository;

import org.springframework.stereotype.Repository;

@Repository
public class DemoRepository {
    public String find() {
        return "Repo - Find";
    }
}

 

결과

 

Controller,Service,Repository에서 @Autowired를 이용하여 DI를 할 수 있는 이유

👉  각각의 어노테이션들이 가지는 메타 어노테이션을 찾아가 보면 @Component가 선언되어 있고, 그로 인해 자동으로 Spring 컨테이너에 Bean으로 등록이 되었고 @Autowired를 이용하여 DI를 할 수 있었던 것이다. 

 

1. Controller의 경우 

// RestController.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 * @since 4.0.1
	 */
	@AliasFor(annotation = Controller.class)
	String value() default "";

}

// Controller.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // 이곳에서 컴포넌트가 선언되어 자동으로 스프링 컨테이너에 Bean으로 등록됨
public @interface Controller {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

 

2. Service의 경우  

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // 이곳에서 컴포넌트가 선언되어 자동으로 스프링 컨테이너에 Bean으로 등록됨
public @interface Service {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

 

3. Repository의 경우 

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // 이곳에서 컴포넌트가 선언되어 자동으로 스프링 컨테이너에 Bean으로 등록됨
public @interface Repository {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}