[java] Spring에서 자동 배선은 어떻게 작동합니까?

나는 방법으로 혼란 조금 해요 제어의 반전 ( IoC)에서 작동합니다 Spring.

인터페이스 UserServiceImpl를 구현 하는 서비스 클래스가 있다고 가정 해보십시오 UserService.

이것은 어떻게 @Autowired될까요?

그리고 내에서 Controllers, 어떻게 것 I 이 서비스를?instantiateinstance

그냥 다음을할까요?

UserService userService = new UserServiceImpl();



답변

첫째, 가장 중요한-모든 스프링 빈은 관리되고 있으며 “응용 프로그램 컨텍스트”라는 컨테이너 안에 “살아”있습니다.

둘째, 각 응용 프로그램에는 해당 컨텍스트에 대한 진입 점이 있습니다. 웹 응용 프로그램에는 서블릿이 있고 JSF 는 el-resolver 등을 사용합니다. 또한 응용 프로그램 컨텍스트가 부트 스트랩되고 모든 Bean이 자동 연결되는 곳이 있습니다. 웹 애플리케이션에서 이것은 시작 리스너 일 수 있습니다.

자동 배선은 한 Bean의 인스턴스를 다른 Bean 인스턴스의 원하는 필드에 배치하여 발생합니다. 두 클래스는 모두 Bean이어야합니다. 즉, 응용 프로그램 컨텍스트에 맞게 정의되어야합니다.

응용 문맥에서 “생존”이란 무엇입니까? 이는 컨텍스트가 사용자가 아닌 객체를 인스턴스화 한다는 것을 의미 합니다. 즉, 절대 만들지 않습니다 new UserServiceImpl(). 컨테이너는 각 주입 지점을 찾아 인스턴스를 설정합니다.

컨트롤러에는 다음이 있습니다.

@Controller // Defines that this class is a spring bean
@RequestMapping("/users")
public class SomeController {

    // Tells the application context to inject an instance of UserService here
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public void login(@RequestParam("username") String username,
           @RequestParam("password") String password) {

        // The UserServiceImpl is already injected and you can use it
        userService.login(username, password);

    }
}

몇 가지 참고 사항 :

  • 당신에 applicationContext.xml당신은 활성화해야 <context:component-scan>수업이 검사되도록 @Controller, @Service등 주석.
  • Spring-MVC 애플리케이션의 진입 점은 DispatcherServlet이지만 숨겨져 있기 때문에 애플리케이션 컨텍스트의 직접적인 상호 작용 및 부트 스트랩은 배후에서 발생합니다.
  • UserServiceImpl주석을 사용 <bean id=".." class="..">하거나 사용 하여 Bean으로 정의해야합니다 @Service. 의 유일한 구현 자이므로 UserService주입됩니다.
  • @Autowired주석 외에도 Spring은 XML 구성 가능한 자동 배선을 사용할 수 있습니다. 이 경우 기존 Bean과 일치하는 이름 또는 유형을 가진 모든 필드는 자동으로 Bean을 가져옵니다. 사실, 그것은 자동 배선의 초기 아이디어였습니다. 필드를 구성하지 않고 의존성으로 필드를 주입하십시오. 다른 주석처럼 @Inject, @Resource또한 사용할 수 있습니다.

답변

주석 경로를 원하는지 아니면 Bean XML 정의 경로를 원하는지에 따라 다릅니다.

에 콩을 정의했다고 가정 해보십시오 applicationContext.xml.

<beans ...>

    <bean id="userService" class="com.foo.UserServiceImpl"/>

    <bean id="fooController" class="com.foo.FooController"/>

</beans>

자동 배선은 응용 프로그램이 시작될 때 발생합니다. 따라서 fooController인수에 대해 UserServiceImpl클래스 를 사용하려는 에서는 다음과 같이 주석을 달 것입니다.

public class FooController {

    // You could also annotate the setUserService method instead of this
    @Autowired
    private UserService userService;

    // rest of class goes here
}

이 표시되면 @AutowiredSpring 은의 속성과 일치하는 클래스를 찾아 applicationContext자동으로 주입합니다. 하나 이상의 UserServiceBean 이있는 경우 사용할 Bean을 규정해야합니다.

다음을 수행하는 경우 :

UserService service = new UserServiceImpl();

@Autowired직접 설정하지 않으면 픽업하지 않습니다 .


답변

@Autowired Spring 2.5에서 소개 된 주석으로, 주입에만 사용됩니다.

예를 들면 다음과 같습니다.

class A {

    private int id;

    // With setter and getter method
}

class B {

    private String name;

    @Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods.
    A a;

    // With setter and getter method

    public void showDetail() {
        System.out.println("Value of id form A class" + a.getId(););
    }
}


답변

@Autowired내부적으로 어떻게 작동합니까?

예:

class EnglishGreeting {
   private Greeting greeting;
   //setter and getter
}

class Greeting {
   private String message;
   //setter and getter
}

.xml 파일을 사용하지 않으면 비슷하게 보입니다 @Autowired.

<bean id="englishGreeting" class="com.bean.EnglishGreeting">
   <property name="greeting" ref="greeting"/>
</bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

당신이 사용하는 @Autowired경우 :

class EnglishGreeting {
   @Autowired //so automatically based on the name it will identify the bean and inject.
   private Greeting greeting;
   //setter and getter
}

.xml 파일을 사용하지 않으면 비슷하게 보입니다 @Autowired.

<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

여전히 의심이 있다면 라이브 데모 아래를 살펴보십시오.

@Autowired는 내부적으로 어떻게 작동합니까?


답변

주석으로 서비스 클래스 UserServiceImpl에 주석 을 달기 만하면 됩니다.

@Service("userService")

스프링 컨테이너는 서비스로 등록 될 때이 클래스의 수명주기를 처리합니다.

그런 다음 컨트롤러에서 자동 배선 (인스턴스화)하고 기능을 사용할 수 있습니다.

@Autowired
UserService userService;


답변

스프링 의존성 주입은 클래스에서 커플 링을 제거하는 데 도움이됩니다. 다음과 같은 객체를 만드는 대신 :

UserService userService = new UserServiceImpl();

DI를 소개 한 후에 이것을 사용할 것입니다 :

@Autowired
private UserService userService;

이를 위해서는 ServiceConfiguration파일에 서비스 Bean을 작성해야 합니다. 그런 다음 해당 ServiceConfiguration클래스를 클래스 로 가져 와서 WebApplicationConfiguration다음과 같이 해당 Bean을 Controller에 자동 와이어 링 할 수 있습니다.

public class AccController {

    @Autowired
    private UserService userService;
} 

현재 자바 구성을 기반으로 POC 찾을 수 있습니다
예를 들어 .


답변

표준 방식 :

@RestController
public class Main {
    UserService userService;

    public Main(){
        userService = new UserServiceImpl();
    }

    @GetMapping("/")
    public String index(){
        return userService.print("Example test");
    }
}

사용자 서비스 인터페이스 :

public interface UserService {
    String print(String text);
}

UserServiceImpl 클래스 :

public class UserServiceImpl implements UserService {
    @Override
    public String print(String text) {
        return text + " UserServiceImpl";
    }
}

산출: Example test UserServiceImpl

이것은 꽉 결합 된 클래스, 나쁜 디자인 예제의 좋은 예이며 테스트에 문제가있을 것입니다 (PowerMockito도 나쁩니다).

이제 느슨한 결합의 좋은 예인 SpringBoot 의존성 주입을 살펴 보자.

인터페이스는 동일하게 유지됩니다.

메인 클래스 :

@RestController
public class Main {
    UserService userService;

    @Autowired
    public Main(UserService userService){
        this.userService = userService;
    }

    @GetMapping("/")
    public String index(){
        return userService.print("Example test");
    }
}

ServiceUserImpl 클래스 :

@Component
public class UserServiceImpl implements UserService {
    @Override
    public String print(String text) {
        return text + " UserServiceImpl";
    }
}

산출: Example test UserServiceImpl

이제 테스트를 작성하기 쉽습니다.

@RunWith(MockitoJUnitRunner.class)
public class MainTest {
    @Mock
    UserService userService;

    @Test
    public void indexTest() {
        when(userService.print("Example test")).thenReturn("Example test UserServiceImpl");

        String result = new Main(userService).index();

        assertEquals(result, "Example test UserServiceImpl");
    }
}

내가 보여 @Autowired생성자에 주석을하지만, 그것은 또한 세터 또는 필드에서 사용할 수 있습니다.