De annotatie @Autowired in Spring wordt gebruikt voor automatische afhankelijkheidsinjectie. Het Spring-framework is gebouwd op afhankelijkheidsinjectie en we injecteren de klassenafhankelijkheden via het configuratiebestand van de spring bean.
Spring @Autowired Annotatie
Meestal verstrekken we de bean-configuratiedetails in het configuratiebestand van de spring bean en specificeren we ook de beans die in andere beans worden geïnjecteerd met behulp van het
ref
attribuut. Maar het Spring-framework biedt ook autowiring-functies waar we de beaninjectiedetails niet expliciet hoeven op te geven. Er zijn verschillende manieren waarop we een Spring bean kunnen autowiren.
- autowire byName – Voor dit type autowiring wordt de setter-methode gebruikt voor afhankelijkheidsinjectie. Ook moet de variabelennaam hetzelfde zijn in de klasse waarin we de afhankelijkheid zullen injecteren en in het configuratiebestand van de spring bean.
- autowire op type – Voor dit type autowiring wordt het klassetype gebruikt. Er zou dus slechts één bean geconfigureerd moeten zijn voor dit type in het configuratiebestand van de lenteboon.
- autowire op constructor – Dit is bijna vergelijkbaar met autowire op type, het enige verschil is dat de constructor wordt gebruikt om de afhankelijkheid in te voegen.
- autowire op autodetecteren – Als u op Spring 3.0 of oudere versies zit, is dit een van de autowire-opties die beschikbaar zijn. Deze optie werd gebruikt voor autowire op constructor of op type, zoals bepaald door de Spring-container. Aangezien we al zoveel opties hebben, is deze optie verouderd. Ik zal deze optie niet behandelen in deze tutorial.
@Autowired
annotatie – We kunnen de Spring @Autowired annotatie gebruiken voor het autowiring van lenteboon. De @Autowired annotatie kan worden toegepast op variabelen en methoden voor autowiring op type. We kunnen ook de @Autowired annotatie gebruiken op de constructor voor op constructor gebaseerd autowiring in de lente. Voor de @Autowired annotatie om te werken, moeten we ook annotatiegebaseerde configuratie inschakelen in het configuratiebestand van de lenteboon. Dit kan worden gedaan door het context:annotation-config element of door het definiëren van een bean van het typeorg.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
.@Qualifier
annotatie – Deze annotatie wordt gebruikt om conflicten in bean-mapping te vermijden en we moeten de bean-naam opgeven die zal worden gebruikt voor automatische bedrading. Op deze manier kunnen we problemen vermijden waarbij meerdere bonen zijn gedefinieerd voor hetzelfde type. Deze annotatie werkt meestal samen met de @Autowired annotatie. Voor constructors met meerdere argumenten kunnen we deze annotatie gebruiken met de argumentnamen in de methode.
Standaard staat de spring bean automatische bedrading uit. De standaardwaarde voor spring bean autowiring is “default”, wat betekent dat er geen automatische bedrading moet worden uitgevoerd. De waarde “no” voor autowire heeft ook hetzelfde gedrag. Om het gebruik van Spring Bean autowiring te demonstreren, laten we een eenvoudig Spring Maven-project maken. Ons uiteindelijke project zal eruit zien als de onderstaande afbeelding. Laten we elk van de autowire-opties één voor één bekijken. Hiervoor zullen we een Model bean en een serviceklasse maken waarin we de model bean zullen injecteren.
Spring @Autowired Annotatie – Maven afhankelijkheden
Voor spring-autobedrading hoeven we geen extra afhankelijkheden toe te voegen. Ons pom.xml-bestand heeft spring framework core afhankelijkheden en ziet er als volgt uit.
<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>
Voorjaar @Autowired Annotation – Model Bean
Laten we een eenvoudige Java Bean maken, genaamd Employee. Deze bean zal een enkele eigenschap hebben met getter- en setter-methoden. We zullen de waarde van deze eigenschap initialiseren in het voorjaarsbonconfiguratiebestand.
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;
}
}
Voorjaar @Autowired Annotation – Serviceklasse
Laten we onze serviceklasse maken waarin we de Employee bean zullen injecteren via voorjaarsautobekabeling.
package com.journaldev.spring.autowiring.service;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeService {
private Employee employee;
// constructor wordt gebruikt voor bekabeling via constructor
public EmployeeService(Employee emp) {
System.out.println("Autowiring by constructor used");
this.employee = emp;
}
// standaardconstructor om BeanInstantiationException te voorkomen voor bekabeling
// op naam of op type
public EmployeeService() {
System.out.println("Default Constructor used");
}
// gebruikt voor bekabeling op naam en op type
public void setEmployee(Employee emp) {
this.employee = emp;
}
public Employee getEmployee() {
return this.employee;
}
}
We zullen dezelfde serviceklasse gebruiken voor het uitvoeren van spring-autobekabeling op basis van naam, type en constructor. De setter-methode wordt gebruikt voor spring-autobekabeling op basis van naam en type, terwijl injectie op basis van de constructor zal worden gebruikt via de autowire-attribuut van de constructor. Wanneer we spring-autobekabeling op basis van naam of type gebruiken, wordt de standaardconstructor gebruikt. Daarom hebben we expliciet de standaardconstructor gedefinieerd voor de EmployeeService-bean.
Spring @Autowired Annotation – Voorbeeld van autowiring op basis van type
Laten we een aparte klasse maken met de Spring @Autowired-annotatie voor autowiring op basis van type.
package com.journaldev.spring.autowiring.service;
import org.springframework.beans.factory.annotation.Autowired;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeAutowiredByTypeService {
// De Autowired-annotatie op variabelen/setters is equivalent aan autowire="byType"
@Autowired
private Employee employee;
@Autowired
public void setEmployee(Employee emp){
this.employee=emp;
}
public Employee getEmployee(){
return this.employee;
}
}
Merk op dat ik zowel de Employee-variabele als de bijbehorende setter-methode heb geannoteerd met de Spring @Autowired-annotatie, maar slechts één daarvan is voldoende voor spring bean-autobekabeling.
Lente@Autowired annotatie en @Qualifier Bean autowiring door constructor Voorbeeld
Laten we een andere serviceklasse maken waar we de @Autowired annotatie zullen gebruiken voor op constructeur gebaseerde injectie. We zullen ook het gebruik van de @Qualifier annotatie zien.
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 annotatie op Constructor is equivalent aan autowire="constructor"
@Autowired(required=false)
public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
this.employee=emp;
}
public Employee getEmployee() {
return this.employee;
}
}
Wanneer deze bean geïnitialiseerd wordt door het Spring-framework, zal de bean met de naam “employee” worden gebruikt voor autowiring. De Spring @Autowired annotatie verwacht één argument “required” dat een boolean is met standaardwaarde TRUE. We kunnen het definiëren als “false”, zodat het Spring-framework geen uitzondering gooit als er geen geschikte bean wordt gevonden voor autowiring.
Spring @Autowired Annotation – Bean Configuration-bestand
Het Spring bean configuratiebestand is het belangrijkste onderdeel van elke Spring-toepassing. Laten we eens kijken hoe ons Spring bean configuratiebestand eruitziet en dan zullen we elk onderdeel ervan bekijken.
<?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>
Belangrijke punten over het Spring bean configuratiebestand zijn:
- beans element
default-autowire
wordt gebruikt om de standaardautobekabelingsmethode te definiëren. Hier definieer ik de standaardautobekabelingsmethode als byName. - beans element
default-autowire-candidates
wordt gebruikt om het patroon voor bean-namen op te geven die kunnen worden gebruikt voor autokoppeling. Voor eenvoud laat ik alle bean-definities toe voor autokoppeling, maar als we een patroon kunnen definiëren voor autokoppeling. Bijvoorbeeld, als we alleen DAO bean-definities willen voor autokoppeling, kunnen we het specificeren alsdefault-autowire-candidates="*DAO"
. autowire-candidate="false"
wordt gebruikt in een bean-definitie om het ongeschikt te maken voor autokoppeling. Het is handig wanneer we meerdere bean-definities hebben voor een enkel type en we willen dat sommige ervan niet worden gekoppeld. Bijvoorbeeld, in bovenstaande Spring bean-configuraties zal de “employee1” bean niet worden gebruikt voor autokoppeling.- autowire-attribuut byName, byType en constructor is vanzelfsprekend, daar valt niet veel over uit te leggen.
context:annotation-config
wordt gebruikt om ondersteuning voor configuratie op basis van annotaties in te schakelen. Let op dat de beans employeeAutowiredByTypeService en employeeAutowiredByConstructorService geen autowire-attributen hebben.
Spring @Autowired Annotation – Testprogramma
Nu onze Spring-toepassing gereed is met alle soorten Spring-autobekabeling, laten we een eenvoudig testprogramma schrijven om te zien of het zoals verwacht werkt of niet.
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());
// hashcode afdrukken om te bevestigen dat alle objecten van verschillend type zijn
System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
// Testen van @Autowired-annotaties
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();
}
}
Het programma is eenvoudig, we creëren gewoon de Spring-toepassingscontext en gebruiken deze om verschillende beans te verkrijgen en de naam van de medewerker af te drukken. Als we het bovenstaande programma uitvoeren, krijgen we de volgende uitvoer.
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
Zoals je kunt zien, wordt voor autowiring byName en byType standaard de no-args constructor gebruikt om het bean te initialiseren. Voor autowiring by constructor wordt de op parameter gebaseerde constructor gebruikt. Uit de hashcode van alle variabelen hebben we bevestigd dat alle Spring beans verschillende objecten zijn en niet verwijzen naar hetzelfde object. Omdat we “employee1” uit de lijst van in aanmerking komende beans voor autowiring hebben verwijderd, was er geen verwarring in de bean-mapping. Als we autowire-candidate="false"
verwijderen uit de definitie van “employee1”, krijgen we de onderstaande foutmelding bij het uitvoeren van de bovenstaande hoofdmethode.
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
Dat is alles voor de Spring @Autowired-annotatie en de Spring-autowiring-functie. Download het voorbeeldproject via onderstaande link en analyseer het om meer te leren.
Source:
https://www.digitalocean.com/community/tutorials/spring-autowired-annotation