האונוטציה @Autowired ב-Spring משמשת להזרקת תלות אוטומטית. סביבת העבודה של Spring מבוססת על הזרקת תלות, ואנו מזריקים את תלותי המחלקות דרך קובץ התצורה של בוני הדברים של Spring.
Spring @Autowired הוא האונוטציה
בדרך כלל אנו מספקים פרטי הגדרת גרעין בקובץ ההגדרה של בוני הדברים של Spring וגם מציינים את הדברים שיוזרו בדברים אחרים באמצעות המאפיין
ref
. אך סביבת העבודה של Spring מספקת גם תכונות להזרקת תלות באופן אוטומטי שבו אין צורך לספק פרטי הזרקת גרעין באופן מפורש. ישנם שיטות שונות שבאמצעותן אנו יכולים להזריק באופן אוטומטי את גרעיני ה-Spring.
- הזרקה לפי שם – לסוג זה של הזרקת תלות, משמשת שיטת הקביעה להזרקת תלות. גם שם המשתנה צריך להיות זהה במחלקה שבה נזריק את התלות ובקובץ ההגדרה של בוני הדברים של Spring.
- העברת סוג על ידי טיפוס – בשביל סוג זה של העברת התלמית, נעשה שימוש בסוג המחלקה. לכן יש רק צורך באחד בלבד מתצורת העדן בקובץ התצורה של העדן.
- העברת על ידי בנאי – זה דומה כמעט להעברת סוג, ההבדל היחיד הוא שנעשה שימוש בבנאי כדי להזרים את התלות.
- העברת סוג על ידי אוטוזדטקט – אם אתה משתמש בספרינג 3.0 או בגרסאות ישנות יותר, זוהי אחת מאפשרויות ההעברה הזמינות. אפשרות זו הייתה בשימוש עבור העברת על ידי בנאי או לפי סוג, כפי שנקבע על ידי מכונת הספרינג. במשום שכבר יש לנו כל כך הרבה אפשרויות, אפשרות זו הוחלפה בפועל. אני לא אכסה את האפשרות הזו במדריך זה.
- הערה
@Autowired
– אפשר להשתמש בהערת @Autowired של ספרינג עבור העברת העדן של העדן. הערת @Autowired ניתן להחיל על משתנים ועל פעולות לצורך העברת העדן לפי סוג. ניתן גם להשתמש בהערת @Autowired על בנאי לצורך העברת העדן בעקבות בנאי. כדי שהערת @Autowired תעבוד, עלינו גם לאפשר הגדרת ערכים מבוססת הערות בקובץ התצורה של העדן. זה ניתן לעשות על ידי הגדרת רכיב context:annotation-config או על ידי הגדרת עדן מסוגorg.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
. @Qualifier
אנטוטציה – האנטוטציה הזו משמשת כדי למנוע סכסוכים במיפוי החליפים ואנו צריכים לספק את שם החליף שיעשה שימוש באופן אוטומטי. בכך אנו יכולים למנוע בעיות שבהן מספר חליפים מוגדרים עבור אותו סוג. האנטוטציה הזו נהוגה רגילות עם האנטוטציה @Autowired. עבור בנאי עם מספר ארגומנטים, אנו יכולים להשתמש באנטוטציה זו עם שמות הארגומנטים במתודה.
ברירת המחדל, האוטומטיות של החליפים של ספרינג מושבתת. ערך ברירת המחדל של אוטומטיות החליפים של ספרינג הוא "ברירת המחדל" שאומר שאין לבצע אוטומטיות. ערך האוטומטיות "לא" גם יש לו את אותה התנהגות. כדי להציג את השימוש באוטומטיות של חליפי ספרינג, בואו ניצור פרויקט Maven פשוט של ספרינג. הפרויקט הסופי שלנו יראה כמו התמונה למטה. בואו נסתכל על כל אחת מהאפשרויות של האוטומטיות אחת לאחת. לכך ניצור חליף מודל ומחליף שירות שבו נזרוק את חליף המודל.
ספרינג @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>
הערות העצמיות @Autowired אינדקציה – מודל בין
בואו ניצור פסקליה פשוטה בג'אווה, שמכונה עובד. בפסקליה זו יהיה לנו מאפיין יחיד עם שיטות getter ו-setter. נאתחל את ערך המאפיין הזה בקובץ הקונפיגורציה של הפסקליה של ספרינג.
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;
}
}
הערות העצמיות @Autowired אינדקציה – מחלקת שירות
בואו ניצור את מחלקת השירות שלנו שבה נזריק את הפסקליה "עובד" דרך האוטואיירינג של ספרינג.
package com.journaldev.spring.autowiring.service;
import com.journaldev.spring.autowiring.model.Employee;
public class EmployeeService {
private Employee employee;
// הבנאי משמש לאוטואייר על ידי בנאי
public EmployeeService(Employee emp) {
System.out.println("Autowiring by constructor used");
this.employee = emp;
}
// בנאי ברירת המחדל כדי למנוע מException לאוטואייר
// לפי שם או לפי סוג
public EmployeeService() {
System.out.println("Default Constructor used");
}
// משמש לאוטואייר לפי שם או לפי סוג
public void setEmployee(Employee emp) {
this.employee = emp;
}
public Employee getEmployee() {
return this.employee;
}
}
נעשה שימוש באותה קבוצת שירות לביצוע אוטואווירינג בשם, בסוג ובבנאי של Spring. השיטת המגדירה תשמש לאוטואווירינג בשם ובסוג בזמן שהבנאי ישמש לאוטואווירינג בתור מאפיין של "autowire". כאשר אנו משתמשים ב- "autowire" של Spring בשם או בסוג, הבנאי המחדל ישמש. לכן, הגדרנו באופן פעיל את הבנאי המחדל עבור ה-Bean של EmployeeService.
Spring @Autowired אוטואווירינג – דוגמה לאוטואווירינג לפי סוג
ניצור כתובת נפרדת עם הוספת הערה של 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 {
// הערה מיועדת לאוטואווירינג בסוג דרך משתנה/setter
@Autowired
private Employee employee;
@Autowired
public void setEmployee(Employee emp){
this.employee=emp;
}
public Employee getEmployee(){
return this.employee;
}
}
שימו לב שהציווי עשוי על שני המשתנים של Employee והשיטה שלו עם הערה של Spring @Autowired, אך רק אחת מתוכן היא מספיקה לאוטואווירינג של בין ה-Beans של Spring.
אביב@Autowired אודות ודוגמא ל־@Qualifier המשמשת בבניית ה־Bean על ידי קונסטרקטור
ניצור שירות נוסף שבו נשתמש בהעברת תלות ב־@Autowired בקונסטרקטור. נראה גם איך להשתמש בהעברת תלות בעזרת @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;
// ההעברה באמצעות הערך על הקונסטרקטור שווה ל־autowire="constructor"
@Autowired(required=false)
public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
this.employee=emp;
}
public Employee getEmployee() {
return this.employee;
}
}
כאשר ה־bean יתבצע יבוצע יבוצע על ידי מסגרת ה־Spring, ה־bean בשם "employee" ישמש להעברת תלות. הערה: השימוש ב־@Autowired מצפה לפרמטר אחד בלבד בשם "required" אשר הערך המוגדר כברירת מחדל הוא TRUE. ניתן להגדיר אותו כ-"false" כך שמסגרת ה־Spring לא תזרוק יוצא דופן אם אין חפיפה מתאימה להעברת התלות.
הערות@Autowired הערה – קובץ הגדרות ביניים של פול.
קובץ הגדרות הפול הוא החלק המרכזי של כל אפליקציה של פול, בואו נראה איך נראה קובץ ההגדרות של הפול שלנו ואז נסתכל על כל חלק בו.
<?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>
נקודות חשובות על קובץ ההגדרות של פול הן:
- אלמנטי הבונים
default-autowire
משמשים להגדיר את שיטת האוטומטית ברירת המחדל. כאן אני מגדיר את שיטת האוטומטי ברירת המחדל להיות לפי שם. - אלמנטי הבונים
default-autowire-candidates
משמשים לספק את התבנית עבור שמות הפול שיכולים לשמש לאוטומטי. לפשטות אני מאפשר את כל ההגדרות של הפול להיות ראויות לאוטומטי, אך אם נוכל להגדיר תבנית מסוימת עבור אוטומטי. לדוגמה, אם נרצה רק הגדרות DAO של הפול לאוטומטי, נוכל לציין את זה כמו כןdefault-autowire-candidates="*DAO"
. autowire-candidate="false"
משמש בהגדרת פול כדי להופיע כלא ראוי לאוטומטי. זה מועיל כאשר יש לנו מספר הגדרות של פול לסוג יחיד ואנו רוצים שחלק מהן לא יופעלו באופן אוטומטי. לדוגמה, בהגדרות פול של הפול של מעלה לא ישמש באופן אוטומטי.- המאפיין autowire לפי שם, לפי סוג ולפי בנאי הוא ברור מעצמו, אין הרבה מה להסביר שם.
- הקוד
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());
// מדפיסים קוד בינארי כדי לאשר שכל האובייקטים הם מסוגים שונים
System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
// בדיקת הערות @Autowired
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
כפי שאתה יכול לראות, עבור autowire byName ו-byType, הבנאי המותאם אוטומטית שלא מקבל פרמטרים ברירת מחדל משמש לאתחול של הבנאי. עבור autowire על ידי בנאי, משתמשים בבנאי המבוסס על פרמטרים. מתוך ערכי ה- hashcode של כל המשתנים, אישרנו שכל ה- spring beans הם אובייקטים שונים ואינם מפנים לאובייקט אותו עצמו. מאחר שהסרנו את "employee1" מרשימת ה-beans המועדפים ל-autowiring, לא הייתה בלבול במיפוי ה-bean. אם נסיר את autowire-candidate="false"
מההגדרה של "employee1", נקבל את ההודעה למטה בעת ביצוע של פעולת ה-main שלמעלה.
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
זהו הכל עבור הערכת ה-@Autowired ותכונת ה-autowiring של Spring, אנא הורד את דוגמת הפרויקט מהקישור למטה ובצע ניתוח כדי ללמוד עוד.
Source:
https://www.digitalocean.com/community/tutorials/spring-autowired-annotation