程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Spring bean依賴注入、bean的裝配及相關注解,springbean

Spring bean依賴注入、bean的裝配及相關注解,springbean

編輯:JAVA綜合教程

Spring bean依賴注入、bean的裝配及相關注解,springbean


依賴注入

Spring主要提供以下兩種方法用於依賴注入

  • 基於屬性Setter方法注入
  • 基於構造方法注入

Setter方法注入

例子:

public class Communication {
 
    private Messaging messaging;
      
     /*
     * DI via Setter
     */
    public void setMessaging(Messaging messaging){
        this.messaging = messaging;
    }
 
    public void communicate(){
        messaging.sendMessage();
    }
}

如上Communication類有一個messaging屬性,並含有setMessaging方法,那麼使用Setter方法注入的時候,只需要使用如下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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" />
 
    <bean id="communication" class="com.websystique.spring.Communication">
        <property name="messaging">
            <ref bean="activeMqMessaging" />
        </property>
    </bean>
 
</beans>

這裡省略了ActiveMQMessaging的定義,實際上ActiveMQMessaging類是Messaging接口的一個實現類。

構造方法注入

例子

public class Communication {
 
    private Encryption encryption;
     
    /*
     * DI via Constructor Injection
     */
    public Communication(Encryption encryption){
        this.encryption = encryption;
    }
 
 
    public void communicate(){
        encryption.encryptData();
    }
 
}

注意以上Communication類有一個構造方法Communication(Encryption encryption),且含有一個入參,類型為Encryption,那麼使用構造方法注入的時候,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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" />
 
    <bean id="communication" class="com.websystique.spring.Communication">
        <constructor-arg type="com.websystique.spring.domain.Encryption">
            <ref bean="rsaEncryption" />
        </constructor-arg>
    </bean>
 
</beans>

注意,這裡省略了RSAEncryption的定義,不用在意這些細節,該類是Encryption接口的一個實現類。

另外,為了避免構造方法重載帶來的歧義,這裡指定了入參類型為com.websystique.spring.domain.Encryption。

裝配

bean的裝配有兩種方式,手動裝配和自動裝配。注意,不要混淆,bean的裝配是依賴注入的具體行為,依賴注入的時候需要根據bean的名稱或類型等進行裝配。

手動裝配:通過在<property> 或者 <constructor>標簽中使用ref屬性,在上一小節的“依賴注入”部分使用的就是手動裝配;

<!-- default example (autowire="no") -->
<bean id="driver" class="com.websystique.spring.domain.Driver">
    <property name="license" ref="license"/>
</bean>
 
<bean id="license" class="com.websystique.spring.domain.License" >
    <property name="number" value="123456ABCD"/>
</bean>

自動裝配:在<bean>標簽中使用autowire屬性;

<bean id="application" class="com.websystique.spring.domain.Application" autowire="byName"/>

本小節主要關注自動裝配,自動裝配有以下四種方式:

  • autowire="byName" : 根據名稱
  • autowire="byType" : 根據類型
  • autowire="constructor" : 根據構造方法入參類型
  • autowire="no" : 不使用自動裝配,即默認方式,手動裝配

autowire="byName"

例子:

public class Application {
 
    private ApplicationUser applicationUser;
 
    public ApplicationUser getApplicationUser() {
        return applicationUser;
    }
 
    public void setApplicationUser(ApplicationUser applicationUser) {
        this.applicationUser = applicationUser;
    }
 
    @Override
    public String toString() {
        return "Application [applicationUser=" + applicationUser + "]";
    }
}

該類有一個屬性叫applicationUser,那麼根據名稱自動裝配的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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <!-- byName example -->
    <bean id="application" class="com.websystique.spring.domain.Application" autowire="byName"/>
 
    <bean id="applicationUser" class="com.websystique.spring.domain.ApplicationUser" >
        <property name="name" value="superUser"/>
    </bean>
</beans>

autowire="byType"

例子

public class Employee {
 
    private EmployeeAddress address;
 
    public EmployeeAddress getAddress() {
        return address;
    }
 
    public void setAddress(EmployeeAddress address) {
        this.address = address;
    }
 
    @Override
    public String toString() {
        return "Employee [address=" + address + "]";
    }
}

該類有一個屬性類型為EmployeeAddress,那麼根據類型自動裝配的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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <!-- byType example -->
    <bean id="employee" class="com.websystique.spring.domain.Employee" autowire="byType"/>
 
    <bean id="employeeAddress" class="com.websystique.spring.domain.EmployeeAddress" >
        <property name="street" value="112/223,SantaVila"/>
        <property name="city" value="Nebraska"/>
    </bean>
 
</beans>

autowire="constructor"

例子

public class Performer {
     
    private Instrument instrument;
     
    public Performer(Instrument instrument){
        this.instrument = instrument;
    }
 
    @Override
    public String toString() {
        return "Performer [instrument=" + instrument + "]";
    }
}

該類有一個構造方法,入參的類型為Instrument,那麼根據構造方法自動裝配的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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <!-- constructor example -->
    <bean id="performer" class="com.websystique.spring.domain.Performer" autowire="constructor"/>
 
    <bean id="instrument" class="com.websystique.spring.domain.Instrument" >
        <property name="name" value="PIANO"/>
    </bean>
 
</beans>

autowire="no"

public class Driver {
 
    private License license;
     
    public void setLicense(License license) {
        this.license = license;
    }
 
    public License getLicense() {
        return license;
    }
 
    @Override
    public String toString() {
        return "Driver [license=" + license + "]";
    }
}

該類有一個屬性license,由於我們不打算使用自動裝配功能,那麼只能使用手動裝配了,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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
    <!-- default example (autowire="no") -->
    <bean id="driver" class="com.websystique.spring.domain.Driver" autowire="no">
        <property name="license" ref="license"/>
    </bean>
 
    <bean id="license" class="com.websystique.spring.domain.License" >
        <property name="number" value="123456ABCD"/>
    </bean>
 
</beans>

注意,如果不配置license的ref引用的話,license將為null。

相關注解

主要涉及以下三個注解

  • @Autowired
  • @Resource
  • @Qualifier

@Autowired可應用於構造方法、屬性、setter方法或配置類@Configuration的方法上,該注解根據bean的數據類型進行裝配,如果你想希望根據bean的名稱進行裝配可以使用帶name屬性的@Resource注解;另外@Qualifier注解經常與@Autowired注解結合使用,用於解決一個應用中存在多個同種類型的bean的情況,下面將給出各個注解的示例。

@Autowired(根據類型自動裝配)

setter方法上

@Component("driver")
public class Driver {
 
    private License license;
     
    @Autowired
    public void setLicense(License license) {
        this.license = license;
    }
 
    @Override
    public String toString() {
        return "Driver [license=" + license + "]";
    }
    //getter
}

構造方法上

@Component("driver")
public class Driver {
 
    private License license;
     
    @Autowired
    public Driver(License license){
        this.license = license;
    }
     
    @Override
    public String toString() {
        return "Driver [license=" + license + "]";
    }
}

屬性上

@Component("driver")
public class Driver {
    @Autowired
    private License license;
     
    //getter,setter
 
    @Override
    public String toString() {
        return "Driver [license=" + license + "]";
    }
}

@Resource(根據名稱裝配)

@Component("application")
public class Application {
 
    @Resource(name="applicationUser")
    private ApplicationUser user;
 
    @Override
    public String toString() {
        return "Application [user=" + user + "]";
    }
}

@Qualifier(與@Autowired結合使用,實現按名稱裝配)

例子背景::存在兩個Car接口的實現類,其中一個Car接口的實現類已被注冊為bean,且name為Mustang

@Component
public class Bond {
 
    @Autowired
    @Qualifier("Mustang")
    private Car car;
     
    public void showCar(){
        car.getCarName();
    }
}

注意,以上例子如果不使用@Qualifier限定的話,將拋出如下異常,表明存在多個類型相同的bean:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.websystique.spring.domain.Car] is defined: expected single matching bean but found 2: Ferari,Mustang
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 14 more

最後提醒下,被@Autowired注解標注默認情況下能保證成功注入,如果注入不成功(往往是找不到,或存在歧義),Spring會拋出異常。當然,有時候可能會有特殊需求,不希望bean被強制裝配,那麼可以在@Autowired上添加required=false屬性,表明該bean的裝配是可選的,找不到的話,就為null吧,如下示例:

@Component("driver")
public class Driver {
    @Autowired(required=false)
    private License license;
     
    //getter,setter
 
    @Override
    public String toString() {
        return "Driver [license=" + license + "]";
    }
}

基於以上原因,雖然@Autowired注解與@Resource功能類似,但是@Autowired還是比@Resource強大了那麼一點點,個人建議使用@Autowired注解。

參考資料

http://websystique.com/spring/spring-dependency-injection-example-with-constructor-and-property-setter-xml-example/

http://websystique.com/spring/spring-beans-auto-wiring-example-using-xml-configuration/

http://websystique.com/spring/spring-dependency-injection-annotation-beans-auto-wiring-using-autowired-qualifier-resource-annotations-configuration/

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved