@TOC
This article Outlines the differences between annotations commonly used in these three Spring applications.
@Resources
@Resources:
The @Resource annotation is part of the JSR-250 annotation collection and is packaged with Jakarta EE.
What is jSR-250? Visit this link: jcp.org/en/jsr/deta…
There are many PDFS to download:
When you open it, you’ll see a document of Java supported annotations. These documents are the most authoritative:
As documented, @Resources injection of beans takes the following priority:
- Match by Name
- Match by Type
- Match by Qualifier
Match by Name
Let’s look at the Match by Name example. The following code attempts to inject a Bean named namedFile with Match by Name:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class FieldResourceInjectionIntegrationTest {
@Resource(name="namedFile")
private File defaultFile;
@Test
public void givenResourceAnnotation_WhenOnField_ThenDependencyValid(a){
assertNotNull(defaultFile);
assertEquals("namedFile.txt", defaultFile.getName()); }}Copy the code
The Bean is defined in the following code:
@Configuration
public class ApplicationContextTestResourceNameType {
@Bean(name="namedFile")
public File namedFile(a) {
File namedFile = new File("namedFile.txt");
returnnamedFile; }}Copy the code
At run time, the Name attribute of the @resource at the declared Bean dependency matches the Name attribute of the @bean at the Bean definition, and the Match by Name test passes.
Match by Type
Remove the name attribute from the @Resource annotation in the consumer code that uses the bean and make it look like this:
@Resource
private File defaultFile;
Copy the code
The test still passes because the Match by Name detection mechanism fails, and the next round of Match by Type detection succeeds.
Match by Qualifier
Define two beans:
@Configuration
public class ApplicationContextTestResourceQualifier {
@Bean(name="defaultFile")
public File defaultFile(a) {
File defaultFile = new File("defaultFile.txt");
return defaultFile;
}
@Bean(name="namedFile")
public File namedFile(a) {
File namedFile = new File("namedFile.txt");
returnnamedFile; }}Copy the code
Test code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceQualifier.class)
public class QualifierResourceInjectionIntegrationTest {
@Resource
private File dependency1;
@Resource
private File dependency2;
@Test
public void givenResourceAnnotation_WhenField_ThenDependency1Valid(a){
assertNotNull(dependency1);
assertEquals("defaultFile.txt", dependency1.getName());
}
@Test
public void givenResourceQualifier_WhenField_ThenDependency2Valid(a){
assertNotNull(dependency2);
assertEquals("namedFile.txt", dependency2.getName()); }}Copy the code
Failed to perform this time, I met abnormal org. Springframework. Beans. Factory. NoUniqueBeanDefinitionException.
The reason is that the Name of the injected Bean was not specified in our test code, so Spring’s Match by Name detection failed. During the Match by Type detection, two beans of the same Type were detected, and the Spring framework did not know which Bean to inject, so an exception was reported.
It is also easy to avoid this exception using @qualifier. The code is as follows:
@Resource
@Qualifier("defaultFile")
private File dependency1;
@Resource
@Qualifier("namedFile")
private File dependency2;
Copy the code
@Inject
This annotation is defined in JSR-330, linked to the document:
Jcp.org/en/jsr/deta…
Injection priority:
- Match by Type
- Match by Qualifier
- Match by Name
Match by Type
Notice The highest priority of @inject is Match by Type, not Match by Name of @resource.
Define an arbitrary Component to inject:
@Component
public class ArbitraryDependency {
private final String label = "Arbitrary Dependency";
public String toString(a) {
returnlabel; }}Copy the code
Inject:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestInjectType.class)
public class FieldInjectIntegrationTest {
@Inject
private ArbitraryDependency fieldInjectDependency;
@Test
public void givenInjectAnnotation_WhenOnField_ThenValidDependency(a){
assertNotNull(fieldInjectDependency);
assertEquals("Arbitrary Dependency", fieldInjectDependency.toString()); }}Copy the code
Match by Qualifier
Define a new component to inject:
public class AnotherArbitraryDependency extends ArbitraryDependency {
private final String label = "Another Arbitrary Dependency";
public String toString(a) {
returnlabel; }}Copy the code
Test code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestInjectQualifier.class)
public class FieldQualifierInjectIntegrationTest {
@Inject
private ArbitraryDependency defaultDependency;
@Inject
private ArbitraryDependency namedDependency;
@Test
public void givenInjectQualifier_WhenOnField_ThenDefaultFileValid(a){
assertNotNull(defaultDependency);
assertEquals("Arbitrary Dependency",
defaultDependency.toString());
}
@Test
public void givenInjectQualifier_WhenOnField_ThenNamedFileValid(a){
assertNotNull(defaultDependency);
assertEquals("Another Arbitrary Dependency", namedDependency.toString()); }}Copy the code
And before @ the Resource for the first time by trying to Match by Type failure injection, encounter exceptions: NoUniqueBeanDefinitionException
Use @qualifier to avoid this exception:
@Inject
@Qualifier("defaultFile")
private ArbitraryDependency defaultDependency;
@Inject
@Qualifier("namedFile")
private ArbitraryDependency namedDependency;
Copy the code
Match by Name
public class YetAnotherArbitraryDependency extends ArbitraryDependency {
private final String label = "Yet Another Arbitrary Dependency";
public String toString(a) {
returnlabel; }}Copy the code
Consumer Code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestInjectName.class)
public class FieldByNameInjectIntegrationTest {
@Inject
@Named("yetAnotherFieldInjectDependency")
private ArbitraryDependency yetAnotherFieldInjectDependency;
@Test
public void givenInjectQualifier_WhenSetOnField_ThenDependencyValid(a){
assertNotNull(yetAnotherFieldInjectDependency);
assertEquals("Yet Another Arbitrary Dependency", yetAnotherFieldInjectDependency.toString()); }}Copy the code
Application Context code:
@Configuration
public class ApplicationContextTestInjectName {
@Bean
public ArbitraryDependency yetAnotherFieldInjectDependency(a) {
ArbitraryDependency yetAnotherFieldInjectDependency =
new YetAnotherArbitraryDependency();
returnyetAnotherFieldInjectDependency; }}Copy the code
The test pass
@Autowired
This annotation is used in the same way as @inject, the only difference being that @AutoWired belongs to the annotation provided by the Spring framework. Example slightly.
For more of Jerry’s original articles, please follow the public account “Wang Zixi “: