웹사이트 검색

스프링 @Autowired 주석


스프링 종속성 주입 및 스프링 빈 구성 파일을 통해 클래스 종속성을 주입합니다.

스프링 @Autowired 주석

  1. autowire byName - 이 유형의 자동 연결의 경우 종속성 주입에 setter 메서드가 사용됩니다. 또한 변수 이름은 종속성을 주입할 클래스와 Spring Bean 구성 파일에서 동일해야 합니다.
  2. autowire byType - 이 유형의 자동 연결에는 클래스 유형이 사용됩니다. 따라서 spring bean 구성 파일에는 이 유형에 대해 구성된 bean이 하나만 있어야 합니다.
  3. autowire by constructor - 이것은 autowire byType과 거의 비슷하지만 유일한 차이점은 생성자가 종속성을 주입하는 데 사용된다는 것입니다.
  4. autodetect에 의한 autowire - Spring 3.0 또는 이전 버전을 사용 중인 경우 사용할 수 있는 autowire 옵션 중 하나입니다. 이 옵션은 Spring 컨테이너에 의해 결정되는 생성자 또는 byType에 의한 autowire에 사용되었습니다. 이미 많은 옵션이 있으므로 이 옵션은 더 이상 사용되지 않습니다. 이 튜토리얼에서는 이 옵션을 다루지 않겠습니다.
  5. @Autowired 주석 - Spring @Autowired 주석을 사용하여 작동할 수 있으며 Spring Bean 구성 파일에서 주석 기반 구성을 활성화해야 합니다. 이는 context:annotation-config 요소 또는 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 유형의 빈을 정의하여 수행할 수 있습니다.
  6. @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 프로젝트 다운로드