Spring @Autowired 주석은 자동 의존성 주입에 사용됩니다. Spring 프레임워크는 의존성 주입에 기반을 두고 있으며, 우리는 스프링 빈 구성 파일을 통해 클래스 의존성을 주입합니다.
Spring @Autowired 주석
일반적으로 우리는 스프링 빈 구성 파일에서 빈 구성 세부 정보를 제공하고, 다른 빈에 주입 될 빈도
ref
속성을 사용하여 지정합니다. 그러나 Spring 프레임워크는 빈 주입 세부 정보를 명시적으로 제공할 필요가 없는 자동 배선 기능도 제공합니다. 스프링 빈을 자동 배선하는 여러 가지 방법이 있습니다.
- autowire byName – 이 유형의 자동 배선에는 의존성 주입에 setter 메서드가 사용됩니다. 또한, 의존성을 주입할 클래스와 스프링 빈 구성 파일에서 변수 이름이 동일해야 합니다.
- autowire byType – 이 유형의 자동 연결에는 클래스 유형이 사용됩니다. 따라서 스프링 빈 구성 파일에이 유형에 대해 구성된 빈은 하나만 있어야합니다.
- autowire by constructor – 이것은 거의 autowire byType과 유사하지만, 차이점은 생성자가 종속성을 주입하는 데 사용된다는 것입니다.
- autowire by autodetect – Spring 3.0이나 이전 버전을 사용하는 경우, 이것은 사용 가능한 autowire 옵션 중 하나입니다. 이 옵션은 Spring 컨테이너에 의해 생성자 또는 byType으로 autowire됩니다. 이미 많은 옵션이 있으므로이 옵션이 deprecate되었습니다. 이 튜토리얼에서 이 옵션을 다루지 않겠습니다.
@Autowired
주석 – 우리는 Spring @Autowired 주석을 spring bean autowiring에 사용할 수 있습니다. @Autowired 주석은 변수 및 메서드에 byType으로 자동 연결하기 위해 적용 할 수 있습니다. 우리는 또한 생성자를 위해 constructor에 대한 @Autowired 주석을 사용할 수 있습니다. @Autowired 주석이 작동하려면 스프링 빈 구성 파일에서 주석 기반 구성을 활성화해야합니다. 이 작업은 context:annotation-config 요소 또는org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
유형의 빈을 정의하여 수행 할 수 있습니다.@Qualifier
어노테이션 – 이 어노테이션은 빈 매핑에서 충돌을 피하기 위해 사용되며 자동 연결에 사용될 빈 이름을 제공해야 합니다. 이를 통해 동일한 유형에 대해 여러 빈이 정의된 경우에 발생할 수 있는 문제를 피할 수 있습니다. 이 어노테이션은 보통@Autowired
어노테이션과 함께 사용됩니다. 여러 인수를 가진 생성자의 경우 메서드에서 인수 이름과 함께 이 어노테이션을 사용할 수 있습니다.
기본적으로 스프링 빈 자동 연결은 꺼져 있습니다. 스프링 빈 자동 연결의 기본값은 “default”로 자동 연결이 수행되지 않음을 의미합니다. “no”라는 autowire 값도 동일한 동작을 합니다. 스프링 빈 자동 연결을 보여주기 위해 간단한 스프링 메이븐 프로젝트를 만들어 봅시다. 최종 프로젝트는 아래 이미지처럼 보일 것입니다. 각 autowire 옵션을 하나씩 살펴보겠습니다. 이를 위해 Model 빈과 해당 빈을 주입할 서비스 클래스를 만들겠습니다.
스프링 @Autowired 어노테이션 – 메이븐 의존성
스프링 자동 연결을 위해 추가적인 종속성을 추가할 필요가 없습니다. 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>
봄@Autowired 주석 – 모델 빈
간단한 Java Bean을 만들어 보겠습니다. 이 Bean에는 getter와 setter 메서드가 있는 단일 속성이 있습니다. 이 속성 값을 스프링 빈 구성 파일에서 초기화할 것입니다.
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;
}
}
봄@Autowired 주석 – 서비스 클래스
스프링 자동 연결을 통해 Employee 빈을 주입할 서비스 클래스를 만들어 보겠습니다.
package com.journaldev.spring.autowiring.service;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeService {
private Employee employee;
// 생성자는 생성자에 의해 자동 연결에 사용됩니다
public EmployeeService(Employee emp) {
System.out.println("Autowiring by constructor used");
this.employee = emp;
}
// 자동 연결로 인한 BeanInstantiationException을 피하기 위한 기본 생성자
// byName 또는 byType
public EmployeeService() {
System.out.println("Default Constructor used");
}
// byName과 byType에 의해 자동 연결에 사용됩니다
public void setEmployee(Employee emp) {
this.employee = emp;
}
public Employee getEmployee() {
return this.employee;
}
}
우리는 byName, byType 및 생성자를 통해 스프링 자동 주입을 수행하는 동일한 서비스 클래스를 사용할 것입니다. Setter 메서드는 byName 및 byType을 위해 스프링 자동 주입에 사용되고 생성자 기반 주입은 생성자 autowire 속성을 사용합니다. 스프링의 byName 또는 byType을 사용할 때는 기본 생성자가 사용됩니다. 그래서 EmployeeService 빈에 대해 명시적으로 기본 생성자를 정의했습니다.
스프링@Autowired 주석 – 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 주석은 autowire="byType"과 동일합니다.
@Autowired
private Employee employee;
@Autowired
public void setEmployee(Employee emp){
this.employee=emp;
}
public Employee getEmployee(){
return this.employee;
}
}
Employee 변수와 해당 세터 메서드에 스프링 @Autowired 주석을 달았음을 유의해주세요. 그러나 이 중 하나만 있어도 스프링 빈 자동 주입에 충분합니다.
봄@Autowired 어노테이션 및 @Qualifier 빈 자동 연결 생성자 예제
다른 서비스 클래스를 만들어 보겠습니다. 여기서 생성자 기반 주입에 @Autowired 어노테이션을 사용할 것입니다. 또한 @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 어노테이션은 autowire="constructor"와 동일합니다.
@Autowired(required=false)
public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
this.employee=emp;
}
public Employee getEmployee() {
return this.employee;
}
}
이 빈이 스프링 프레임워크에 의해 초기화될 때, “employee”라는 이름의 빈이 자동 연결에 사용됩니다. 스프링 @Autowired 어노테이션은 “required”라는 하나의 인수를 예외로 받습니다. 이는 기본값으로 TRUE를 갖습니다. “false”로 정의하여 적합한 빈이 자동 연결에 찾을 수 없을 경우 스프링 프레임워크가 예외를 throw하지 않도록 할 수 있습니다.
Spring @Autowired 주석 – 빈 구성 파일
스프링 빈 구성 파일은 모든 스프링 애플리케이션의 주요 부분입니다. 이제 우리의 스프링 빈 구성 파일이 어떻게 보이는지 살펴보고, 그 다음에는 각 부분을 살펴보겠습니다.
<?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>
스프링 빈 구성 파일에 대한 중요한 점은 다음과 같습니다:
- beans 요소
default-autowire
는 기본 자동 연결 방법을 정의하는 데 사용됩니다. 여기서는 기본 자동 연결 방법을 byName으로 정의하고 있습니다. - beans 요소
default-autowire-candidates
는 자동 연결에 사용할 수있는 빈 이름에 대한 패턴을 제공하는 데 사용됩니다. 간단히 말해서, 모든 빈 정의가 자동 연결에 적격하도록 허용하고 있지만, 자동 연결을 위한 일부 패턴을 정의할 수 있습니다. 예를 들어, DAO 빈 정의만 자동 연결하려면default-autowire-candidates="*DAO"
로 지정할 수 있습니다. autowire-candidate="false"
는 빈 정의에서 자동 연결에 적합하지 않도록합니다. 단일 유형에 대해 여러 빈 정의가있고 일부는 자동 연결되지 않도록하려는 경우 유용합니다. 예를 들어, 위의 스프링 빈 구성에서 “employee1” 빈은 자동 연결에 사용되지 않습니다.- autowire 속성 byName, byType 및 constructor는 자명하며 설명할 것이 별로 없습니다.
context:annotation-config
은 어노테이션 기반 구성 지원을 활성화하는 데 사용됩니다. employeeAutowiredByTypeService 및 employeeAutowiredByConstructorService 빈에는 autowire 속성이 없음에 유의하십시오.
Spring @Autowired 어노테이션 – 테스트 프로그램
이제 모든 유형의 Spring 자동 연결이 준비된 상태에서 예상대로 작동하는지 확인하기 위해 간단한 테스트 프로그램을 작성해 봅시다.
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());
// 모든 객체가 다른 유형임을 확인하기 위해 해시코드를 인쇄합니다.
System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
// @Autowired 어노테이션 테스트
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
보시다시피 autowire byName 및 byType을 위해 기본 no-args 생성자가 빈을 초기화하는 데 사용됩니다. 생성자별 autowire의 경우 매개변수 기반 생성자가 사용됩니다. 모든 변수의 해시코드에서 모든 스프링 빈이 다른 객체임을 확인했습니다. “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 어노테이션 및 Spring 자동 연결 기능에 대한 설명은 여기까지입니다. 아래 링크에서 예제 프로젝트를 다운로드하여 자세히 알아보십시오.
Source:
https://www.digitalocean.com/community/tutorials/spring-autowired-annotation