나는 방법으로 혼란 조금 해요 제어의 반전 ( IoC
)에서 작동합니다 Spring
.
인터페이스 UserServiceImpl
를 구현 하는 서비스 클래스가 있다고 가정 해보십시오 UserService
.
이것은 어떻게 @Autowired
될까요?
그리고 내에서 Controllers
, 어떻게 것 I 이 서비스를?instantiate
instance
그냥 다음을할까요?
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
}
이 표시되면 @Autowired
Spring 은의 속성과 일치하는 클래스를 찾아 applicationContext
자동으로 주입합니다. 하나 이상의 UserService
Bean 이있는 경우 사용할 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>
여전히 의심이 있다면 라이브 데모 아래를 살펴보십시오.
답변
주석으로 서비스 클래스 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
생성자에 주석을하지만, 그것은 또한 세터 또는 필드에서 사용할 수 있습니다.