스프링 @Autowired 주석
스프링 종속성 주입 및 스프링 빈 구성 파일을 통해 클래스 종속성을 주입합니다.
스프링 @Autowired 주석
- autowire byName - 이 유형의 자동 연결의 경우 종속성 주입에 setter 메서드가 사용됩니다. 또한 변수 이름은 종속성을 주입할 클래스와 Spring Bean 구성 파일에서 동일해야 합니다.
- autowire byType - 이 유형의 자동 연결에는 클래스 유형이 사용됩니다. 따라서 spring bean 구성 파일에는 이 유형에 대해 구성된 bean이 하나만 있어야 합니다.
- autowire by constructor - 이것은 autowire byType과 거의 비슷하지만 유일한 차이점은 생성자가 종속성을 주입하는 데 사용된다는 것입니다.
- autodetect에 의한 autowire - Spring 3.0 또는 이전 버전을 사용 중인 경우 사용할 수 있는 autowire 옵션 중 하나입니다. 이 옵션은 Spring 컨테이너에 의해 결정되는 생성자 또는 byType에 의한 autowire에 사용되었습니다. 이미 많은 옵션이 있으므로 이 옵션은 더 이상 사용되지 않습니다. 이 튜토리얼에서는 이 옵션을 다루지 않겠습니다.
@Autowired
주석 - Spring @Autowired 주석을 사용하여 작동할 수 있으며 Spring Bean 구성 파일에서 주석 기반 구성을 활성화해야 합니다. 이는 context:annotation-config 요소 또는org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
유형의 빈을 정의하여 수행할 수 있습니다.@Qualifier
주석 - 이 주석은 빈 매핑에서 충돌을 피하기 위해 사용되며 자동 연결에 사용될 빈 이름을 제공해야 합니다. 이렇게 하면 동일한 유형에 대해 여러 빈이 정의되는 문제를 피할 수 있습니다. 이 주석은 일반적으로 @Autowired 주석과 함께 작동합니다. 인수가 여러 개인 생성자의 경우 메소드의 인수 이름과 함께 이 주석을 사용할 수 있습니다.
Spring @Autowired 주석 - Maven 종속성
스프링 자동 배선의 경우 추가 종속성을 추가할 필요가 없습니다. pom.xml 파일에는 스프링 프레임워크 핵심 종속성이 있으며 아래와 같습니다.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringBeanAutowiring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.2.RELEASE</spring-framework.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Spring @Autowired 주석 - 모델 빈
Employee라는 간단한 Java Bean을 생성해 보겠습니다. 이 빈은 getter 및 setter 메서드가 있는 단일 속성을 갖습니다. Spring Bean 구성 파일에서 이 속성 값을 초기화합니다.
package com.journaldev.spring.autowiring.model;
public class Employee {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Spring @Autowired 주석 - 서비스 클래스
Spring autowiring을 통해 Employee bean을 주입할 서비스 클래스를 생성해 봅시다.
package com.journaldev.spring.autowiring.service;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeService {
private Employee employee;
// constructor is used for autowire by constructor
public EmployeeService(Employee emp) {
System.out.println("Autowiring by constructor used");
this.employee = emp;
}
// default constructor to avoid BeanInstantiationException for autowire
// byName or byType
public EmployeeService() {
System.out.println("Default Constructor used");
}
// used for autowire byName and byType
public void setEmployee(Employee emp) {
this.employee = emp;
}
public Employee getEmployee() {
return this.employee;
}
}
이름, 유형 및 생성자별로 스프링 자동 연결을 수행하기 위해 동일한 서비스 클래스를 사용합니다. setter 메서드는 byName 및 byType 스프링 자동 연결에 사용되는 반면 생성자 기반 주입은 생성자 autowire 속성에서 사용됩니다. 스프링 autowire byName 또는 byType을 사용할 때 기본 생성자가 사용됩니다. 이것이 EmployeeService bean의 기본 생성자를 명시적으로 정의한 이유입니다.
Spring @Autowired 주석 - autowiring byType 예제
byType 자동 연결을 위해 Spring @Autowired 주석을 사용하여 별도의 클래스를 생성해 봅시다.
package com.journaldev.spring.autowiring.service;
import org.springframework.beans.factory.annotation.Autowired;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeAutowiredByTypeService {
//Autowired annotation on variable/setters is equivalent to autowire="byType"
@Autowired
private Employee employee;
@Autowired
public void setEmployee(Employee emp){
this.employee=emp;
}
public Employee getEmployee(){
return this.employee;
}
}
Employee 변수와 setter 메서드에 Spring @Autowired 주석을 추가했지만 스프링 빈 자동 연결에는 이 중 하나만 충분합니다.
생성자에 의한 Spring @Autowired Annotation 및 @Qualifier Bean autowiring 예제
@Qualifier 주석 사용을 사용할 또 다른 서비스 클래스를 생성해 보겠습니다.
package com.journaldev.spring.autowiring.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeAutowiredByConstructorService {
private Employee employee;
//Autowired annotation on Constructor is equivalent to autowire="constructor"
@Autowired(required=false)
public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
this.employee=emp;
}
public Employee getEmployee() {
return this.employee;
}
}
이 bean이 Spring 프레임워크에 의해 초기화될 때 이름이 "employee\인 bean이 autowiring에 사용됩니다. Spring @Autowired 주석은 기본값이 TRUE인 부울인 "required\ 인수를 제외합니다. autowiring에 적합한 bean이 발견되지 않으면 스프링 프레임워크가 예외를 던지지 않도록 "false\로 정의할 수 있습니다.
Spring @Autowired 주석 - Bean 구성 파일
Spring bean 구성 파일은 모든 스프링 애플리케이션의 주요 부분입니다. Spring bean 구성 파일이 어떻게 보이는지 확인한 다음 각 부분을 살펴보겠습니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.0.xsd"
default-autowire="byName" default-autowire-candidates="*" >
<bean name="employee" class="com.journaldev.spring.autowiring.model.Employee">
<property name="name" value="Pankaj"></property>
</bean>
<bean name="employee1" class="com.journaldev.spring.autowiring.model.Employee" autowire-candidate="false">
<property name="name" value="Dummy Name"></property>
</bean>
<!-- autowiring byName, bean name should be same as the property name -->
<bean name="employeeServiceByName" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="byName" />
<!-- autowiring byType, there should be only one bean definition for the mapping -->
<bean name="employeeServiceByType" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="byType" />
<!-- autowiring by constructor -->
<bean name="employeeServiceConstructor" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="constructor" />
<!-- Enable Annotation based configuration -->
<context:annotation-config />
<!-- using @Autowiring annotation in below beans, byType and constructor -->
<bean name="employeeAutowiredByTypeService" class="com.journaldev.spring.autowiring.service.EmployeeAutowiredByTypeService" />
<bean name="employeeAutowiredByConstructorService" class="com.journaldev.spring.autowiring.service.EmployeeAutowiredByConstructorService" />
</beans>
Spring Bean 구성 파일에 대한 중요한 사항은 다음과 같습니다.
- beans 요소
default-autowire
는 기본 autowiring 방법을 정의하는 데 사용됩니다. 여기에서는 기본 autowiring 방법을 byName으로 정의하고 있습니다. - beans 요소
default-autowire-candidates
는 autowiring에 사용할 수 있는 bean 이름에 대한 패턴을 제공하는 데 사용됩니다. 단순함을 위해 나는 모든 bean 정의가 autowiring에 적합하도록 허용하고 있지만 autowiring에 대한 일부 패턴을 정의할 수 있다면 가능합니다. 예를 들어, autowiring을 위한 DAO 빈 정의만 원한다면default-autowire-candidates=\*DAO\
로 지정할 수 있습니다. autowire-candidate=\false\
는 빈 정의에서 autowiring에 적합하지 않게 만드는 데 사용됩니다. 단일 유형에 대한 여러 bean 정의가 있고 그 중 일부가 autowired되지 않기를 원할 때 유용합니다. 예를 들어 위의 스프링 빈 구성에서 "employee1\ 빈은 자동 연결에 사용되지 않습니다.- autowire 속성 byName, byType 및 생성자는 자체적으로 이해되며 별다른 설명이 없습니다.
context:annotation-config
는 주석 기반 구성 지원을 활성화하는 데 사용됩니다. employeeAutowiredByTypeService 및 employeeAutowiredByConstructorService 빈에는 autowire 속성이 없습니다.
Spring @Autowired 주석 - 테스트 프로그램
이제 우리의 스프링 애플리케이션이 모든 유형의 스프링 자동 배선으로 준비되었으므로 예상대로 작동하는지 확인하기 위해 간단한 테스트 프로그램을 작성해 보겠습니다.
package com.journaldev.spring.autowiring.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.autowiring.service.EmployeeAutowiredByConstructorService;
import com.journaldev.spring.autowiring.service.EmployeeAutowiredByTypeService;
import com.journaldev.spring.autowiring.service.EmployeeService;
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
EmployeeService serviceByName = ctx.getBean("employeeServiceByName", EmployeeService.class);
System.out.println("Autowiring byName. Employee Name="+serviceByName.getEmployee().getName());
EmployeeService serviceByType = ctx.getBean("employeeServiceByType", EmployeeService.class);
System.out.println("Autowiring byType. Employee Name="+serviceByType.getEmployee().getName());
EmployeeService serviceByConstructor = ctx.getBean("employeeServiceConstructor", EmployeeService.class);
System.out.println("Autowiring by Constructor. Employee Name="+serviceByConstructor.getEmployee().getName());
//printing hashcode to confirm all the objects are of different type
System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
//Testing @Autowired annotations
EmployeeAutowiredByTypeService autowiredByTypeService = ctx.getBean("employeeAutowiredByTypeService",EmployeeAutowiredByTypeService.class);
System.out.println("@Autowired byType. Employee Name="+autowiredByTypeService.getEmployee().getName());
EmployeeAutowiredByConstructorService autowiredByConstructorService = ctx.getBean("employeeAutowiredByConstructorService",EmployeeAutowiredByConstructorService.class);
System.out.println("@Autowired by Constructor. Employee Name="+autowiredByConstructorService.getEmployee().getName());
ctx.close();
}
}
프로그램은 간단합니다. 스프링 애플리케이션 컨텍스트를 생성하고 이를 사용하여 다른 빈을 가져오고 직원 이름을 인쇄하는 것입니다. 위의 응용 프로그램을 실행하면 다음과 같은 결과가 나타납니다.
Mar 31, 2014 10:41:58 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Mon Mar 31 22:41:58 PDT 2014]; root of context hierarchy
Mar 31, 2014 10:41:58 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Default Constructor used
Default Constructor used
Autowiring by constructor used
Autowiring byName. Employee Name=Pankaj
Autowiring byType. Employee Name=Pankaj
Autowiring by Constructor. Employee Name=Pankaj
21594592::15571401::1863015320
@Autowired byType. Employee Name=Pankaj
@Autowired by Constructor. Employee Name=Pankaj
Mar 31, 2014 10:41:58 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Mon Mar 31 22:41:58 PDT 2014]; root of context hierarchy
보시다시피 byName 및 byType 자동 연결의 경우 기본 no-args 생성자가 bean을 초기화하는 데 사용됩니다. 생성자에 의한 autowire의 경우 매개변수 기반 생성자가 사용됩니다. 모든 변수의 해시코드에서 모든 Spring Bean이 동일한 객체를 참조하는 것이 아니라 서로 다른 객체임을 확인했습니다. autowiring에 적합한 빈 목록에서 "employee1\을 제거했기 때문에 빈 매핑에 혼란이 없었습니다. "employee1\ 정의에서 autowire-candidate=\false\
를 제거하면 위의 기본 메소드를 실행할 때 아래 오류 메시지가 표시됩니다.
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employeeServiceByType' defined in class path resource [spring.xml]: Unsatisfied dependency expressed through bean property 'employee': : No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1278)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1170)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.journaldev.spring.autowiring.main.SpringMain.main(SpringMain.java:12)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1263)
... 13 more
Spring @Autowired Annotation 및 Spring autowiring 기능에 대한 내용은 여기까지입니다. 아래 링크에서 예제 프로젝트를 다운로드하고 분석하여 자세히 알아보세요.
Spring Bean Autowiring 프로젝트 다운로드