Field Injection이란 정확히 무엇이며 어떻게 피할 수 있습니까?
나는에 대한 몇 가지 게시물에 읽기 Spring MVC
및 Portlets
필드 주입하지 않는 것이 좋습니다 그. 왜냐하면 나는 얻기 위해 노력하고 있기 때문에 필드 주입을 사용하고 있는지 스스로에게 물었고 대답 할 수 없습니다. 내가 이해하기 때문에 필드 주입 은 다음 Bean
과 @Autowired
같이 속성에 주입하는 것입니다.
CartController.java :
...
@Autowired
private Cart cart;
...
BookshopConfiguartion.java :
@Configuration
public class BookShopConfiguration {
@Bean
public Cart cart(){
return new Cart();
}
//more configuration
My Cart.java
는 카트에있는 책에 대한 정보를 저장하고 제공하는 데 사용됩니다.
내 연구 중에 생성자 주입 에 대해 읽었습니다 .
MyComponent.java :
...
public class MyComponent{
private Cart cart;
@Autowired
public MyComponent(Cart cart){
this.cart = cart;
}
...
이 두 가지 유형의 주사의 장점과 단점은 무엇입니까?
편집 1 : 이 질문의 중복으로 표시되기 때문에 이 질문에 내가 그것을 확인. 질문이나 답변에 코드 예제가 없기 때문에 내가 어떤 주입 유형을 사용하고 있는지 내 추측에 맞다면 분명하지 않습니다.
주입 유형
종속성을 Bean에 삽입하는 방법에는 세 가지 옵션이 있습니다.
- 생성자를 통해
- setter 또는 기타 방법을 통해
- 반사를 통해 직접 필드로
당신은 옵션 3을 사용하고 있습니다. 그것은 당신이 @Autowired
당신의 분야에서 직접 사용할 때 일어나는 일 입니다.
주입 지침
Spring에서 권장 하는 일반 가이드 라인 ( 생성자 기반 DI 또는 Setter 기반 DI 섹션 참조 )은 다음과 같습니다.
- 필수 종속성 또는 불변성을 목표로 할 때 생성자 주입을 사용하십시오.
- 선택적 또는 변경 가능한 종속성의 경우 setter 주입을 사용하십시오.
- 대부분의 경우 필드 주입을 피하십시오
현장 주입 단점
필드 주입이 눈살을 찌푸리는 이유는 다음과 같습니다.
- 생성자 주입으로 할 수 있듯이 변경 불가능한 객체를 만들 수 없습니다.
- 클래스는 DI 컨테이너와 긴밀하게 연결되어 있으며 외부에서 사용할 수 없습니다.
- 클래스는 리플렉션없이 인스턴스화 할 수 없습니다 (예 : 단위 테스트에서). 이를 인스턴스화하려면 DI 컨테이너가 필요하므로 테스트가 통합 테스트와 비슷해집니다.
- 실제 종속성은 외부에서 숨겨지며 인터페이스 (생성자 또는 메서드)에 반영되지 않습니다.
- 10 개 정도의 의존성을 갖는 것은 정말 쉽습니다. 생성자 주입을 사용하는 경우 10 개의 인수가 포함 된 생성자가있을 것입니다. 그러나 필드 주입을 사용하여 주입 된 필드를 무기한 추가 할 수 있습니다. 종속성이 너무 많으면 클래스가 일반적으로 두 가지 이상의 작업을 수행하고 단일 책임 원칙을 위반할 수 있다는 위험 신호입니다.
결론
필요에 따라 주로 생성자 주입 또는 생성자와 세터 주입의 혼합을 사용해야합니다. 현장 주입에는 많은 단점이 있으므로 피해야합니다. 필드 주입의 유일한 장점은 모든 단점을 능가하지 않는 쓰기가 더 편리하다는 것입니다.
추가 읽기
I wrote a blog article about why field injection is usually not recommended: Field Dependency Injection Considered Harmful.
This is one of the never-ending discussions in software development, but major influencers in the industry are getting more opinionated about the topic and started to suggest constructor injection as the better option.
Constructor injection
Pros:
- Better testability. You do not need any mocking library or a Spring context in unit tests. You can create an object that you want to test with the new keyword. Such tests are always faster because they not rely on the reflection mechanism. (This question was asked 30 minutes later. If the author had used constructor injection it would have not appeared).
- Immutability. Once the dependencies are set they cannot be changed.
- Safer code. After execution of a constructor your object is ready to use as you can validate anything that was passed as a parameter. The object can be either ready or not, there is no state in-between. With field injection you an introduce intermediate step when the object is fragile.
- Cleaner expression of mandatory dependencies. Field injection is ambiguous in this matter.
- Makes developers think about the design. dit wrote about a constructor with 8 parameters, which actually is the sign of a bad design and the God object anti-pattern. It does not matter whether a class has 8 dependencies in its constructor or in fields, it is always wrong. People are more reluctant to add more dependencies to a constructor than via fields. It works as a signal to your brain that you should stop for a while and think about your code structure.
Cons:
- More code (but modern IDEs alleviate the pain).
Basically, the field injection is the opposite.
Matter of taste. It is your decision.
But I can explain, why I never use constructor injection.
I don't want to implement a constructor for all my
@Service
,@Repository
and@Controller
beans. I mean, there are about 40-50 beans or more. Every time if I add a new field I would have to extend the constructor. No. I don't want it and I don't have to.What if your Bean (Service or Controller) requires a lot of other beans to be injected? A constructor with 8 parameters is very ugly.
If I'm using CDI, constructor does not concern me.
EDIT: Vojtech Ruzicka said:
class has too many dependencies and is probably violating single responsibility principle and should be refactored
Yes. Theory and reality. Here is en example: DashboardController
mapped to single path *:8080/dashboard
.
My DashboardController
collects a lot of informations from other services to display them in a dashboard / system overview page. I need this single controller. So I have to secure only this one path (basic auth or user role filter).
참고URL : https://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it
'code' 카테고리의 다른 글
AFNetworking으로 시간 제한을 설정하는 방법 (0) | 2020.10.09 |
---|---|
Laravel 유효성 검사 속성 "Nice names" (0) | 2020.10.09 |
JSON 결과를 날짜로 변환 (0) | 2020.10.09 |
Scala 목록을 튜플로 변환 하시겠습니까? (0) | 2020.10.09 |
Maven 리소스 필터링이 작동하지 않음-스프링 부트 종속성으로 인해 (0) | 2020.10.09 |