Frühling @Autowired Annotation

Frühling @Autowired-Annotation wird für automatische Dependency Injection verwendet. Der Spring-Framework basiert auf Dependency Injection und wir fügen die Klassendependenzen über die Spring Bean-Konfigurationsdatei ein.

Frühling @Autowired-Annotation

Normalerweise geben wir die Bean-Konfigurationsdetails in der Spring Bean-Konfigurationsdatei an und geben auch die Beans an, die in anderen Beans über das ref-Attribut injiziert werden. Das Spring-Framework bietet jedoch auch automatische Verkabelungsfunktionen, bei denen wir die Bean-Injektionsdetails nicht explizit angeben müssen. Es gibt verschiedene Möglichkeiten, wie wir eine Frühlingsbohne automatisch verdrahten können.

  1. autowire byName – Für diese Art der Verkabelung wird die Setter-Methode für die Dependency Injection verwendet. Auch der Variablenname sollte in der Klasse, in der wir die Abhängigkeit injizieren werden, und in der Spring Bean-Konfigurationsdatei gleich sein.
  2. autowire byType – Für diese Art des Autowirings wird der Klassentyp verwendet. Es sollte also nur ein Bean für diesen Typ in der Spring-Bean-Konfigurationsdatei konfiguriert sein.
  3. autowire by constructor – Dies ist fast ähnlich wie autowire byType, der einzige Unterschied besteht darin, dass der Konstruktor verwendet wird, um die Abhängigkeit einzufügen.
  4. autowire by autodetect – Wenn Sie Spring 3.0 oder ältere Versionen verwenden, ist dies eine der verfügbaren Autowire-Optionen. Diese Option wurde für Autowire by constructor oder byType verwendet, wie vom Spring-Container festgelegt. Da wir bereits so viele Optionen haben, ist diese Option veraltet. Ich werde diese Option nicht in diesem Tutorial behandeln.
  5. @Autowired-Annotation – Wir können die Spring @Autowired-Annotation für das Autowiring von Spring-Beans verwenden. Die @Autowired-Annotation kann auf Variablen und Methoden angewendet werden, um autowiring byType durchzuführen. Wir können die @Autowired-Annotation auch auf den Konstruktor anwenden, um das autowiring basierend auf dem Konstruktor zu ermöglichen. Damit die @Autowired-Annotation funktioniert, müssen wir auch die annotationsbasierte Konfiguration in der Spring-Bean-Konfigurationsdatei aktivieren. Dies kann durch das context:annotation-config-Element oder durch Definieren eines Beans vom Typ org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor erfolgen.
  6. Die Annotation @Qualifier wird verwendet, um Konflikte bei der Bean-Zuordnung zu vermeiden, und wir müssen den Bean-Namen angeben, der für die automatische Verdrahtung verwendet wird. Auf diese Weise können wir Probleme vermeiden, bei denen mehrere Beans für denselben Typ definiert sind. Diese Annotation funktioniert normalerweise mit der @Autowired-Annotation. Für Konstruktoren mit mehreren Argumenten können wir diese Annotation mit den Argumentnamen in der Methode verwenden.

Standardmäßig ist die Spring-Bean-Autoverdrahtung deaktiviert. Der Standardwert für die Spring-Bean-Autoverdrahtung ist „default“, was bedeutet, dass keine Autoverdrahtung durchgeführt werden soll. Der Autoverdrahtungswert „no“ hat auch dasselbe Verhalten. Um die Verwendung der Spring-Bean-Autoverdrahtung zu demonstrieren, erstellen wir ein einfaches Spring-Maven-Projekt. Unser endgültiges Projekt wird wie auf dem folgenden Bild aussehen. Schauen wir uns nun nacheinander die einzelnen Autoverdrahtungsoptionen an. Dafür erstellen wir eine Model-Bean und eine Serviceklasse, in der wir die Model-Bean einfügen werden.

Frühling @Autowired Annotation – Maven-Abhängigkeiten

Für die Frühjahrsautoverdrahtung müssen wir keine zusätzlichen Abhängigkeiten hinzufügen. Unsere pom.xml-Datei hat Spring Framework Core-Abhängigkeiten und sieht wie folgt aus.

<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>

Frühling @Autowired Annotation – Modell-Bean

Erstellen wir eine einfache Java-Bean namens Employee. Diese Bean wird eine einzelne Eigenschaft mit Getter- und Setter-Methoden haben. Wir werden den Wert dieser Eigenschaft in der Spring-Bean-Konfigurationsdatei initialisieren.

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;
	}
}

Frühling @Autowired Annotation – Serviceklasse

Erstellen wir unsere Serviceklasse, in der wir die Employee-Bean durch Spring-Autowiring injizieren werden.

package com.journaldev.spring.autowiring.service;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeService {

	private Employee employee;

	// Der Konstruktor wird für das Autowiring durch Konstruktor verwendet
	public EmployeeService(Employee emp) {
		System.out.println("Autowiring by constructor used");
		this.employee = emp;
	}

	// Standardkonstruktor, um eine BeanInstantiationException für das Autowiring zu vermeiden
	// nachName oder nachTyp
	public EmployeeService() {
		System.out.println("Default Constructor used");
	}

	// Verwendet für das Autowiring nachName und nachTyp
	public void setEmployee(Employee emp) {
		this.employee = emp;
	}

	public Employee getEmployee() {
		return this.employee;
	}
}

Wir werden dieselbe Serviceklasse verwenden, um die Spring-Autowiring nach Namen, Typ und Konstruktor durchzuführen. Die Setter-Methode wird für das Spring-Autowiring nach Namen und Typ verwendet, während die konstruktorbasierte Injektion durch das Attribut „autowire“ des Konstruktors verwendet wird. Wenn wir das Spring-Autowiring nach Namen oder Typ verwenden, wird der Standardkonstruktor verwendet. Deshalb haben wir explizit den Standardkonstruktor für das Bean „EmployeeService“ definiert.

Frühling @Autowired Annotation – Beispiel für Autowiring nach Typ

Erstellen wir eine separate Klasse mit der Spring @Autowired Annotation für das Autowiring nach Typ.

package com.journaldev.spring.autowiring.service;

import org.springframework.beans.factory.annotation.Autowired;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeAutowiredByTypeService {

	// Die @Autowired-Annotation auf Variablen/Settern entspricht autowire="byType"
	@Autowired
	private Employee employee;
	
	@Autowired
	public void setEmployee(Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee(){
		return this.employee;
	}
}

Beachten Sie, dass ich sowohl die Employee-Variablen als auch ihre Setter-Methode mit der Spring @Autowired-Annotation versehen habe, jedoch ist nur eine davon ausreichend für das Spring-Bean-Autowiring.

Feder @Autowired Annotation und @Qualifier Bean-Autowiring per Konstruktorbeispiel

Erstellen wir eine weitere Serviceklasse, in der wir die @Autowired-Annotation für die injektion durch den Konstruktor verwenden. Wir werden auch die Verwendung der @Qualifier-Annotation sehen.

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;

	// Die @Autowired-Annotation am Konstruktor entspricht autowire="constructor"
	@Autowired(required=false)
	public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee() {
		return this.employee;
	}
}

Wenn dieses Bean vom Spring-Framework initialisiert wird, wird das Bean mit dem Namen „employee“ für das Autowiring verwendet. Die Spring-@Autowired-Annotation akzeptiert ein Argument „required“, das ein boolescher Wert mit dem Standardwert TRUE ist. Wir können es auf „false“ setzen, damit das Spring-Framework keine Ausnahme auslöst, wenn kein geeignetes Bean für das Autowiring gefunden wird.

Frühling@Autowired Annotation – Bean-Konfigurationsdatei

Die Spring-Bean-Konfigurationsdatei ist der Hauptbestandteil jeder Spring-Anwendung. Schauen wir uns an, wie unsere Spring-Bean-Konfigurationsdatei aussieht, und dann werden wir uns jeden Teil davon genauer ansehen.

<?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>

Wichtige Punkte zur Spring-Bean-Konfigurationsdatei sind:

  • beans-Element default-autowire wird verwendet, um die Standard-Autowiring-Methode zu definieren. Hier definiere ich die Standard-Autowiring-Methode als „byName“.
  • beans-Element default-autowire-candidates wird verwendet, um das Muster für Bean-Namen bereitzustellen, die für Autowiring verwendet werden können. Zur Vereinfachung erlaube ich allen Bean-Definitionen, für Autowiring geeignet zu sein. Wenn wir jedoch ein Muster für das Autowiring definieren können. Zum Beispiel, wenn wir nur DAO-Bean-Definitionen für das Autowiring verwenden möchten, können wir es als default-autowire-candidates="*DAO" festlegen.
  • autowire-candidate="false" wird in einer Bean-Definition verwendet, um sie für das Autowiring ungeeignet zu machen. Es ist nützlich, wenn wir mehrere Bean-Definitionen für einen einzelnen Typ haben und einige von ihnen nicht autowired werden sollen. Zum Beispiel wird in den obigen Spring-Bean-Konfigurationen die Bean „employee1“ nicht für das Autowiring verwendet.
  • autowire-Attribut byName, byType und Konstruktor sind selbsterklärend, nichts weiter zu erklären.
  • context:annotation-config wird verwendet, um die Unterstützung für konfigurationsbasierte Annotationen zu aktivieren. Beachten Sie, dass die Beans employeeAutowiredByTypeService und employeeAutowiredByConstructorService keine Autowire-Attribute haben.

Spring @Autowired Annotation – Testprogramm

Da unsere Spring-Anwendung jetzt mit allen Arten von Spring-Autowiring bereit ist, schreiben wir ein einfaches Testprogramm, um zu sehen, ob es wie erwartet funktioniert oder nicht.

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());
		
		// Druck des Hashcodes zur Bestätigung, dass alle Objekte unterschiedliche Typen haben
		System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
		
		// Testen von @Autowired-Annotationen
		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();
	}
}

Das Programm ist einfach: Wir erstellen den Spring-Anwendungskontext und verwenden ihn, um verschiedene Beans abzurufen und den Mitarbeiter-Namen auszudrucken. Bei Ausführung der obigen Anwendung erhalten wir die folgende Ausgabe.

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

Wie Sie sehen können, verwendet die Autowire byName- und byType-Funktion den Standard-No-Args-Konstruktor, um das Bean zu initialisieren. Bei Autowire by Constructor wird der parameterbasierte Konstruktor verwendet. Anhand des Hashcodes aller Variablen haben wir bestätigt, dass alle Spring-Beans unterschiedliche Objekte sind und nicht auf dasselbe Objekt verweisen. Da wir „employee1“ aus der Liste der geeigneten Beans für die Autowiring entfernt haben, gab es keine Verwirrung bei der Bean-Zuordnung. Wenn wir autowire-candidate="false" aus der Definition von „employee1“ entfernen, erhalten wir die folgende Fehlermeldung beim Ausführen der obigen main-Methode.

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

Das ist alles zur Spring @Autowired-Annotation und zur Spring-Autowiring-Funktion. Bitte laden Sie das Beispielprojekt über den folgenden Link herunter und analysieren Sie es, um mehr zu erfahren.

Spring Bean Autowiring-Projekt herunterladen

Source:
https://www.digitalocean.com/community/tutorials/spring-autowired-annotation