Java Spring의 주입 주석에 의존하는 다양한 차이점 이해

주입 주입은 말 그대로 주입을 통해 이루어지는 것이다. 스프링과 주입과 관련된 흔한 주해는 Autowired, Resource, Qualifier, Service, Controller, Repository, Component이다.
Autowired는 자동으로 주입되며, 스프링의 상하문에서 적합한 bean을 자동으로 찾아 주입합니다.
이름 주입을 지정하는 리소스
Qualifier와 Autowired를 함께 사용하여 bean의 이름을 지정합니다.
서비스, Controller, Repository는 각각 서비스 층 클래스, Controller 층 클래스, 데이터 저장 층 클래스,spring 스캐닝 주석 설정을 표시할 때 이 클래스들이 bean을 생성해야 한다고 표시합니다.
Component는 일종의 범지이다. 태그 클래스는 구성 요소이고spring 주석 설정을 스캔할 때 이 클래스들이 bean을 생성하도록 표시한다.
Bean에 대한 Spring 의존 주입은 다음과 같은 다양한 메모 방식을 지원합니다.

@Resource 
javax.annotation 
JSR250 (Common Annotations for Java) 
@Inject 
javax.inject 
JSR330 (Dependency Injection for Java) 
@Autowired 
org.springframework.bean.factory 
Spring 
직관적으로 보면 @Autowired는 Spring에서 제공하는 주석이고 다른 몇 개는 JDK 자체에 내장된 주석이며 Spring은 이러한 주석을 지원한다.그런데 이 세 가지를 사용하면 도대체 어떤 차이가 있을까요?필자는 방법의 테스트를 통해 재미있는 특성을 발견하였다.
차이점은 다음과 같습니다.
1. @Autowired에는 false로 설정할 수 있는 required 속성이 있습니다. 이 경우 대응하는 bean을 찾지 못하면 이상을 던지지 않습니다. @Inject 및 @Resource는 적절한 구성을 제공하지 않으므로 반드시 찾아야 합니다. 그렇지 않으면 예외가 발생합니다.
2. @Autowired와 @Inject는 기본적으로 같다. 왜냐하면 둘 다 Autowired Annotation BeanPostProcessor를 사용하여 의존 주입을 처리하기 때문이다.그러나 @Resource는 예외입니다. 의존 주입을 처리하기 위해CommonAnnotation BeanPostProcessor를 사용합니다.물론 둘 다 BeanPostProcessor입니다.

@Autowired @Inject 
-   autowired by type 
-    @Qualifier   autowired by qualifier name。 
-   autowired by type  ( ), autowired by field name 
@Resource 
-   autowired by field name 
-   autowired by field name ,  autowired by type 
-    @Qualifier   autowired by qualifier name 
-   autowired by qualifier name ,  autowired by field name。  autowired by field name , autowired by type 。 
TIPS Qualified name VS Bean name
스프링 디자인에서 Qualifiedname은 Beanname과 같지 않고 후자는 유일해야 하지만 전자는 tag나 그룹과 유사한 작용으로 특정한 bean을 분류한다.getByTag(group) 효과를 얻을 수 있습니다.XML 설정의 bean에 대해 id 속성을 통해 beanname (지정하지 않은 경우 기본적으로 클래스 이름 이니셜 소문자 사용) 을 지정하고, 탭을 통해 qualifier name 을 지정할 수 있습니다.

<bean id="lamborghini" class="me.arganzheng.study.spring.autowired.Lamborghini"> 
<qualifier value="luxury"/> 
<!-- inject any dependencies required by this bean --> 
</bean>
메모를 사용하는 경우 @Qualifier 메모를 통해 qualifier name, @Named 또는 @Component(@Service, @Repository 등)의value 값을 통해 bean name을 지정할 수 있습니다.

@Component("lamborghini") 
@Qualifier("luxury") 
public class Lamborghini implements Car { 
} 
혹은

@Component 
@Named("lamborghini") 
@Qualifier("luxury") 
public class Lamborghini implements Car { 
} 
마찬가지로 beanname이 지정되지 않으면 Spring은 기본적으로 클래스 이름의 이니셜 소문자 (Lamborghini=>lamborghini) 를 사용합니다.
3. Anotation 주입 의존 방식을 통해 XML 주입 방식 이전에 진행한다.만약 같은 bean에 대한 의존이 두 가지 주입 방식을 동시에 사용한다면 XML의 우선이다.그러나 Anotation을 통해 주입된 의존은 XML에 설정된 bean에 주입할 수 없다는 우려와 달리 의존 주입은 bean의 등록 후에 이루어진다.
4. 현재의 autowired by type 방식(필자가 사용한 것은 3.2.3.RELEASE 버전), Spring의 Autowired Annotation BeanPost Processor 실현은 모두'bug'가 있다. 즉, @Autowired와 @Inject는 모두 구덩이가 있다는 것이다.이것은 온라인에서 유래한 버그이자 이 글의 작성 원인이다.현장은 다음과 같습니다.
application-context.xml에는 다음과 같은 정의가 있습니다.

<xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:util="http://www.springframework.org/schema/util" 
xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> 
<context:annotation-config /> 
<context:component-scan base-package="me.arganzheng.study" /> 
<util:constant id="en" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.EN" /> 
<util:constant id="ja" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.JP" /> 
<util:constant id="ind" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.IND" /> 
<util:constant id="pt" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.PT" /> 
<util:constant id="th" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.TH" /> 
<util:constant id="ar" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.AR" /> 
<util:constant id="en-rIn" 
static-field="me.arganzheng.study.spring.autowired.Constants.Language.EN_RIN" /> 
<util:map id="languageChangesMap" key-type="java.lang.String" 
value-type="java.lang.String"> 
<entry key="pt" value="pt" /> 
<entry key="br" value="pt" /> 
<entry key="jp" value="ja" /> 
<entry key="ja" value="ja" /> 
<entry key="ind" value="ind" /> 
<entry key="id" value="ind" /> 
<entry key="en-rin" value="en-rIn" /> 
<entry key="in" value="en-rIn" /> 
<entry key="en" value="en" /> 
<entry key="gb" value="en" /> 
<entry key="th" value="th" /> 
<entry key="ar" value="ar" /> 
<entry key="eg" value="ar" /> 
</util:map> 
</beans> 
여기서 static-field 응용 프로그램의 상수 정의는 다음과 같습니다.

package me.arganzheng.study.spring.autowired; 
public interface Constants { 
public interface Language { 
public static final String EN = "CommonConstants.LANG_ENGLISH"; 
public static final String JP = "CommonConstants.LANG_JAPANESE"; 
public static final String IND = "CommonConstants.LANG_INDONESIAN"; 
public static final String PT = "CommonConstants.LANG_PORTUGUESE"; 
public static final String TH = "CommonConstants.LANG_THAI"; 
public static final String EN_RIN = "CommonConstants.LANG_ENGLISH_INDIA"; 
public static final String AR = "CommonConstants.LANG_Arabic"; 
} 
} 
그리고 만약 우리가 코드에서 다음과 같이 의존을 선언한다면

public class AutowiredTest extends BaseSpringTestCase { 
@Autowired 
private Map<String, String> languageChangesMap; 
@Test 
public void testAutowired() { 
notNull(languageChangesMap); 
System.out.println(languageChangesMap.getClass().getSimpleName()); 
System.out.println(languageChangesMap); 
} 
} 
Guess what, 괴이한 일이 일어났다!
실행 결과는 다음과 같습니다.

LinkedHashMap 
{en=CommonConstants.LANG_ENGLISH, ja=CommonConstants.LANG_JAPANESE, ind=CommonConstants.LANG_INDONESIAN, pt=CommonConstants.LANG_PORTUGUESE, th=CommonConstants.LANG_THAI, ar=CommonConstants.LANG_Arabic, en-rIn=CommonConstants.LANG_ENGLISH_INDIA} 
그러니까 맵.
심각: TestExecutionListener를 허용하는 동안 Caught 예외

[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@5c51ee0a] to prepare test instance [me.arganzheng.study.spring.autowired.AutowiredTest@6e301e0] 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'me.arganzheng.study.spring.autowired.AutowiredTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.Map me.arganzheng.study.spring.autowired.AutowiredTest.languageChangesMap; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
... 
ed by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986) 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:843) 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768) 
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) 
... 28 more 
debug를 해보니 확실히 Spring의 버그입니다.Default Listable BeanFactory의 이 방법에 문제가 생겼습니다.

protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName, 
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { 
... 
else if (Map.class.isAssignableFrom(type) && type.isInterface()) { 
Class<?> keyType = descriptor.getMapKeyType(); 
if (keyType == null || !String.class.isAssignableFrom(keyType)) { 
if (descriptor.isRequired()) { 
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() + 
"] must be assignable to [java.lang.String]"); 
} 
return null; 
} 
Class<?> valueType = descriptor.getMapValueType(); 
if (valueType == null) { 
if (descriptor.isRequired()) { 
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]"); 
} 
return null; 
} 
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); 
if (matchingBeans.isEmpty()) { 
if (descriptor.isRequired()) { 
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); 
} 
return null; 
} 
if (autowiredBeanNames != null) { 
autowiredBeanNames.addAll(matchingBeans.keySet()); 
} 
return matchingBeans; 
} 
... 
}
관건은 이 문장: Map
심각: TestExecutionListener를 허용하는 동안 Caught 예외

[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@9476189] to prepare test instance [me.arganzheng.study.spring.autowired.AutowiredTest@2d546e21] 
... 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=languageChangesMap)} 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986) 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:843) 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768) 
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) 
... 28 more 
debug를 보니 지정되지 않은 qualifiename과 같은 실행 경로입니다.Bean name 지정했잖아요.왜 autowired by type일까요?자세히 살펴보니Default Listable BeanFactory의 doResolve Dependency 방법은 먼저 유형에 대해 구별했다.

protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName, 
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { 
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); 
if (value != null) { 
if (value instanceof String) { 
String strVal = resolveEmbeddedValue((String) value); 
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); 
value = evaluateBeanDefinitionString(strVal, bd); 
} 
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 
return (descriptor.getField() != null ? 
converter.convertIfNecessary(value, type, descriptor.getField()) : 
converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); 
} 
if (type.isArray()) { 
Class<?> componentType = type.getComponentType(); 
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor); 
if (matchingBeans.isEmpty()) { 
if (descriptor.isRequired()) { 
raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor); 
} 
return null; 
} 
if (autowiredBeanNames != null) { 
autowiredBeanNames.addAll(matchingBeans.keySet()); 
} 
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 
return converter.convertIfNecessary(matchingBeans.values(), type); 
} 
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { 
Class<?> elementType = descriptor.getCollectionType(); 
if (elementType == null) { 
if (descriptor.isRequired()) { 
throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]"); 
} 
return null; 
} 
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor); 
if (matchingBeans.isEmpty()) { 
if (descriptor.isRequired()) { 
raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor); 
} 
return null; 
} 
if (autowiredBeanNames != null) { 
autowiredBeanNames.addAll(matchingBeans.keySet()); 
} 
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 
return converter.convertIfNecessary(matchingBeans.values(), type); 
} 
else if (Map.class.isAssignableFrom(type) && type.isInterface()) { 
Class<?> keyType = descriptor.getMapKeyType(); 
if (keyType == null || !String.class.isAssignableFrom(keyType)) { 
if (descriptor.isRequired()) { 
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() + 
"] must be assignable to [java.lang.String]"); 
} 
return null; 
} 
Class<?> valueType = descriptor.getMapValueType(); 
if (valueType == null) { 
if (descriptor.isRequired()) { 
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]"); 
} 
return null; 
} 
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); 
if (matchingBeans.isEmpty()) { 
if (descriptor.isRequired()) { 
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); 
} 
return null; 
} 
if (autowiredBeanNames != null) { 
autowiredBeanNames.addAll(matchingBeans.keySet()); 
} 
return matchingBeans; 
} 
else { 
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); 
if (matchingBeans.isEmpty()) { 
if (descriptor.isRequired()) { 
raiseNoSuchBeanDefinitionException(type, "", descriptor); 
} 
return null; 
} 
if (matchingBeans.size() > 1) { 
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor); 
if (primaryBeanName == null) { 
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); 
} 
if (autowiredBeanNames != null) { 
autowiredBeanNames.add(primaryBeanName); 
} 
return matchingBeans.get(primaryBeanName); 
} 
// We have exactly one match. 
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); 
if (autowiredBeanNames != null) { 
autowiredBeanNames.add(entry.getKey()); 
} 
return entry.getValue(); 
} 
} 
Array, Collection 또는 Map의 경우 집합 클래스의 요소 유형에 따라 autowired by type (Map은value를 사용하는 형식) 을 사용합니다.왜 이렇게 특수하게 처리합니까?원래 스프링은 이러한 목적을 달성하기 위해서였다. 당신이 한 번에 모든 유형에 맞는 실현을 주입할 수 있도록 하는 것이다. 즉, 이렇게 주입할 수 있다는 것이다.
@Autowired
private List cars;
만약 당신의 차가 여러 가지 실현이 있다면, 모두 주입할 것이며, 다시 보고하지 않을 것이다

org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No unique bean of type [me.arganzheng.study.spring.autowired.Car] is defined: 
expected single matching bean but found 2: [audi, toyota]. 
그러나 위의 경우 @Resource를 사용하면 다음과 같은 문제가 발생하지 않습니다.

public class AutowiredTest extends BaseSpringTestCase { 
@Resource 
@Qualifier("languageChangesMap") 
private Map<String, String> languageChangesMap; 
@Test 
public void testAutowired() { 
assertNotNull(languageChangesMap); 
System.out.println(languageChangesMap.getClass().getSimpleName()); 
System.out.println(languageChangesMap); 
} 
}
정상 작동:

LinkedHashMap 
{pt=pt, br=pt, jp=ja, ja=ja, ind=ind, id=ind, en-rin=en-rIn, in=en-rIn, en=en, gb=en, th=th, ar=ar, eg=ar} 
물론, @Qualifier ("language Changes Map") 를 지정하지 않으면,field name이 language Changes Map이 아니라면, 똑같이 잘못 보고합니다.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.annotation.Resource(shareable=true, mappedName=, description=, name=, type=class java.lang.Object, authenticationType=CONTAINER, lookup=)} 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986) 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:843) 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768) 
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:438) 
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416) 
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550) 
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150) 
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303) 
... 26 more 
또한 @Resource 는 위의 List 수신을 모두 수행할 수 있습니다.

public class AutowiredTest extends BaseSpringTestCase { 
@Resource 
@Qualifier("languageChangesMap") 
private Map<String, String> languageChangesMap; 
@Resource 
private List<Car> cars; 
@Test 
public void testAutowired() { 
assertNotNull(languageChangesMap); 
System.out.println(languageChangesMap.getClass().getSimpleName()); 
System.out.println(languageChangesMap); 
assertNotNull(cars); 
System.out.println(cars.getClass().getSimpleName()); 
System.out.println(cars); 
} 
}
잘 작동:

LinkedHashMap 
{pt=pt, br=pt, jp=ja, ja=ja, ind=ind, id=ind, en-rin=en-rIn, in=en-rIn, en=en, gb=en, th=th, ar=ar, eg=ar} 
ArrayList 
[me.arganzheng.study.spring.autowired.Audi@579584da, me.arganzheng.study.spring.autowired.Toyota@19453122]
이것은 @Resource 주석이 CommonAnnotation BeanPostProcessor 프로세서를 사용하기 때문에 Autowired Annotation BeanPostProcessor와 같은 작가가 아니기 때문이다.여기는 분석하지 않겠습니다. 관심 있는 학생들은 스스로 코드를 보고 연구할 수 있습니다.
최종 결론은 다음과 같습니다.
1, @Autowired 및 @Inject
autowired by type은 @Qualifier 현식을 통해 autowired by qualifier name (비집합 클래스입니다. 주의: autowired by bean name이 아닙니다!)
autowired by type이 실패하거나 여러 개의 실행을 찾을 수 없으면 autowired by field name (비집합 클래스) 으로 퇴화합니다
2、@Resource
기본 autowired by field name
autowired by field name이 실패하면 autowired by type으로 퇴화됩니다.
@Qualifier 현식으로 autowired by qualifier name을 지정할 수 있습니다.
autowired by qualifier name이 실패하면 autowired by field name으로 퇴화됩니다.하지만 이때 autowired by field name이 실패하면 autowired by type으로 퇴화하지 않습니다.
테스트 프로젝트는 GitHub에 저장되어 있으며 표준 마븐 프로젝트입니다. 관심 있는 학생들은 clone에서 로컬로 테스트를 실행할 수 있습니다.
보충하다
어떤 동료는 스프링 공식 문서에 이런 말이 나와 약간 충돌한다고 지적했다.
However, although you can use this convention to refer to specific beans by name, @Autowired is fundamentally about type-driven injection with optional semantic qualifiers. This means that qualifier values, even with the bean name fallback, always have narrowing semantics within the set of type matches; they do not semantically express a reference to a unique bean id.
즉, @Autowired는 @Qualifier 메모를 추가해도 autowired by type입니다. @Qualifier는 단지 한정어일 뿐, 필터 조건일 뿐이다.코드를 다시 따라가니 확실히 이렇다.Spring에서 디자인한 이 @Qualifier name은 bean name과 같지 않습니다.그는 약간 태그와 유사하다.그러나 만약에 이 태그가 유일한 화이라면 사실 효과는 beanname와 같다.Spring은 먼저 getByType을 받아list candicates를 얻은 다음qualifiername에 따라 필터를 합니다.
람보르기니를 정의합니다. @Qualifier를 사용하여 지정합니다.

package me.arganzheng.study.spring.autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.stereotype.Component; 
@Component 
@Qualifier("luxury") 
public class Lamborghini implements Car { 
} 
로슬레스를 정의합니다. 여기에서 일부러 @Named로 지정합니다.

package me.arganzheng.study.spring.autowired; 
import javax.inject.Named; 
import org.springframework.stereotype.Component; 
@Component 
@Named("luxury") 
public class RollsRoyce implements Car { 
} 
정의된 호화차를 주입하는 테스트를 해보세요.

package me.arganzheng.study.spring.autowired; 
import static junit.framework.Assert.assertNotNull; 
import java.util.List; 
import me.arganzheng.study.BaseSpringTestCase; 
import org.junit.Test; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
/** 
* 
* @author zhengzhibin 
* 
*/ 
public class AutowiredTest extends BaseSpringTestCase { 
@Autowired 
@Qualifier("luxury") 
private List<Car> luxuryCars; 
@Test 
public void testAutowired() { 
assertNotNull(luxuryCars); 
System.out.println(luxuryCars.getClass().getSimpleName()); 
System.out.println(luxuryCars); 
} 
}
실행 결과는 다음과 같습니다.

ArrayList 
[me.arganzheng.study.spring.autowired.Lamborghini@66b875e1, me.arganzheng.study.spring.autowired.RollsRoyce@58433b76] 
보충: Autowiring modes
Spring은 네 가지 autowire 모드를 지원합니다. XML 설정 방식을 사용할 때 autowire 속성을 통해 지정할 수 있습니다.

no. (Default) No autowiring. Bean references must be defined via a ref element. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system. 
byName. Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name, and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master, and uses it to set the property. 
byType. Allows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens; the property is not set. 
constructor. Analogous to byType, but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised. 
@Autowired, @Inject 또는 @Resource 메모를 사용할 때 약간 복잡하고 실패 퇴화 과정이 있으며 Qualifier를 도입했습니다.하지만 기본 원리는 같다.

좋은 웹페이지 즐겨찾기