None Dependancy Injection
class EmployeesSalariesReportService {
void generateReport() {
EmployeeDao employeeDao = new EmployeeDao();
List<Employee> employees = employeeDao.findAll();
EmployeeSalaryCalculator employeeSalaryCalculator = new EmployeeSalaryCalculator();
List<EmployeeSalary> employeeSalaries = employeeSalaryCalculator.calculateSalaries(employees);
PdfSalaryReport pdfSalaryReport = new PdfSalaryReport();
pdfSalaryReport.writeReport(employeeSalaries);
}
}
public class Runner {
public static void main(String... args) {
EmployeesSalariesReportService employeesSalariesReportService = new EmployeesSalariesReportService();
employeesSalariesReportService.generateReport();
}
}
Manual Dependancy Injection
class EmployeesSalariesReportService {
private final EmployeeDao employeeDao;
private final EmployeeSalaryCalculator employeeSalaryCalculator;
private final SalaryReport salaryReport;
EmployeesSalariesReportService(EmployeeDao employeeDao, EmployeeSalaryCalculator employeeSalaryCalculator, SalaryReport salaryReport) {
this.employeeDao = employeeDao;
this.employeeSalaryCalculator = employeeSalaryCalculator;
this.salaryReport = salaryReport;
}
void generateReport() {
List<Employee> employees = employeeDao.findAll();
List<EmployeeSalary> employeeSalaries = employeeSalaryCalculator.calculateSalaries(employees);
salaryReport.writeReport(employeeSalaries);
}
}
public class Runner {
public static void main(String... args) {
EmployeesSalariesReportService employeesSalariesReportService = new EmployeesSalariesReportService(
new EmployeeDao(),
new EmployeeSalaryCalculator(),
new PdfSalaryReport()
);
employeesSalariesReportService.generateReport();
}
}
Dependancy Injection By Spring (Application Context)
@ComponentScan
public class Configuration {}
@Service
class EmployeesSalariesReportService {
private final EmployeeDao employeeDao;
private final EmployeeSalaryCalculator employeeSalaryCalculator;
private final SalaryReport salaryReport;
EmployeesSalariesReportService(EmployeeDao employeeDao, EmployeeSalaryCalculator employeeSalaryCalculator, SalaryReport salaryReport) {
this.employeeDao = employeeDao;
this.employeeSalaryCalculator = employeeSalaryCalculator;
this.salaryReport = salaryReport;
}
void generateReport() {
List<Employee> employees = employeeDao.findAll();
List<EmployeeSalary> employeeSalaries = employeeSalaryCalculator.calculateSalaries(employees);
salaryReport.writeReport(employeeSalaries);
}
}
public class Runner {
public static void main(String... args) {
AnnotationConfigApplicationContext context = getSpringContext("pdf-reports");
EmployeesSalariesReportService employeesSalariesReportService = context.getBean(EmployeesSalariesReportService.class);
employeesSalariesReportService.generateReport();
context.close();
}
private static AnnotationConfigApplicationContext getSpringContext(String profile) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles(profile);
context.register(Configuration.class);
context.refresh();
return context;
}
}
@Service
)을 통해 서비스 구현체를 컴포넌트로 등록한다@Autowired
어노테이션을 사용하여 의존성을 주입하며 어노테이션 선언 위치에 따라 세가지 방식으로 의존성 주입이 가능하다@Autowired
어노테이션 생략 가능@Autowired(required = false)
옵션을 통해 의존성 객체가 존재 하지 않는것을 허용 가능(nullable dependancy)테스트 시 문제점
유닛 테스트 환경에서는 스프링 애플리케이션 컨택스트를 직접적으로 생성하지 않을 수 있고 이러한 경우에는 의존성 객체가 주입되지 않아 NullPointerException 런타임 에러가 발생하게 된다.
final
키워드 사용) final
로 선언되었기 때문에 의존성 객체가 반드시 주입 되었음을 보장한다인터페이스 빈
@Profile
, @Qualifier
어노테이션을 지원함으로써 인터페이스로 선언된 의존성의 경우 런타임 시점에 동적으로 인터페이스 구현체를 주입하도록 하여 확장에 열려있는 소프트웨어 설계가 가능하도록 한다**@Profile
: 구현체가 특정 프로파일(실행환경) 에서만 생성되도록 설정할 수 있다**인터페이스만을 지원하기 위해 사용하는 것은 아니며 프로파일 설정에 따라 다른 빈들을 매핑할 수 있도록 하는 어노테이션
애플리케이션 컨텍스트에서 하나 이상의 프로파일이 지정하고 구현체에 @Profile
어노테이션을 통해 프로파일을 명시하면 특정 프로파일마다 매핑될 구현체를 선택할 수 있다.
@Component
@Profile("pdf-reports")
public class PdfSalaryReport implements SalaryReport {
public void writeReport(List<EmployeeSalary> employeeSalaries) {
System.out.println("Writing Pdf Report");
}
}
@Qualifier
@Componet("find-name")
**@Autowired**
)와 함께 @Qualifier("찾는이름")
을 작성해야 한다