@Component
public class MadExample {
@Autowired
private HelloService helloService;
}
@Component
public class MadExample {
private HelloService helloService;
@Autowired
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
@Component
public class MadExample {
// final로 선언할 수 있는 보너스
private final HelloService helloService;
// 단일 생성자인 경우는 추가적인 어노테이션이 필요 없다.
public MadExample(HelloService helloService) {
this.helloService = helloService;
}
}
@Service
public class MadPlayService {
// 순환 참조
@Autowired
private MadLifeService madLifeService;
public void sayMadPlay() {
madLifeService.sayMadLife();
}
}
@Service
public class MadLifeService {
// 순환 참조
@Autowired
private MadPlayService madPlayService;
public void sayMadLife() {
madPlayService.sayMadPlay();
}
}
//위의 경우 실행은되나 runtime error발생됨
java.lang.StackOverflowError: null
at com.example.demo.GreetService.sayGreet(GreetService.java:12) ~[classes/:na]
at com.example.demo.HelloService.sayHello(HelloService.java:12) ~[classes/:na]
at com.example.demo.GreetService.sayGreet(GreetService.java:12) ~[classes/:na]
at com.example.demo.HelloService.sayHello(HelloService.java:12) ~[classes/:na]
at com.example.demo.GreetService.sayGreet(GreetService.java:12) ~[classes/:na]
@Service
public class MadPlayService {
private final MadLifeService madLifeService;
public MadPlayService(MadLifeService madLifeService) {
this.madLifeService = madLifeService;
}
// 생략
}
@Service
public class MadLifeService {
private final MadPlayService madPlayService;
public MadLifeService(MadPlayService madPlayService) {
this.madPlayService = madPlayService;
}
// 생략
}
// 컴파일 단계에서 에러발생
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| madLifeService defined in file [~~~/MadLifeService.class]
↑ ↓
| madPlayService defined in file [~~~/MadPlayService.class]
└─────┘
SomeObject someObject = new SomeObject();
MadComponent madComponent = new MadComponent(someObject);
madComponent.someMadPlay();
@Component
public class MadComponent {
// 물론 이런 경우는 거의 드물겠지만...
@Autowired
private FirstComponent firstComponent;
@Autowired
private SecondComponent secondComponent;
@Autowired
private NumberComponent numberComponent;
@Autowired
private SomeComponent someComponent;
@Autowired
private StrangeComponent strangeComponent;
}
@Service
public class MadPlayService {
private final MadPlayRepository madPlayRepository;
public MadPlayService(MadPlayRepository madPlayRepository) {
this.madPlayRepository = madPlayRepository;
}
}
//또는 잘못된 변경을 막을수 있음
@Service
public class MadPlayService {
@Autowired
private MadPlayRepository madPlayRepository;
public void someMethod() {
// final이 아니기 때문에 값을 변경할 수 있다.
madPlayRepository = null;
madPlayRepository.call();
}
}
//final 사용에 null을 넣으려고 해서 Error를 발견하기 쉬움
@Service
public class MadPlayService {
private final MadPlayRepository madPlayRepository;
public MadPlayService(MadPlayRepository madPlayRepository) {
this.madPlayRepository = madPlayRepository;
}
public void someMethod() {
// cannot assign a value to final variable
madPlayRepository = null;
}
}
https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection