Spring註解詳解

原來咱們是怎麼作的java

在使用註釋配置以前,先來回顧一下傳統上是如何配置 Bean 並完成 Bean 之間依賴關係的創建。下面是 3 個類,它們分別是 Office、Car 和 Boss,這 3 個類須要在 Spring 容器中配置爲 Bean:spring

Office 僅有一個屬性:ide

package com.baobaotao;
public class Office {
    private String officeNo =」001」;

    //省略 get/setter

    @Override
    public String toString() {
        return "officeNo:" + officeNo;
    }
}


Car 擁有兩個屬性:函數

package com.baobaotao;

public class Car {
    private String brand;
    private double price;

    // 省略 get/setter

    @Override
    public String toString() {
        return "brand:" + brand + "," + "price:" + price;
    }
}

Boss 擁有 Office 和 Car 類型的兩個屬性:post


package com.baobaotao;

public class Boss {
    private Car car;
    private Office office;

    // 省略 get/setter

    @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}

咱們在 Spring 容器中將 Office 和 Car 聲明爲 Bean,並注入到 Boss Bean 中:下面是使用傳統 XML 完成這個工做的配置文件 beans.xml:this

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="boss" class="com.baobaotao.Boss">
        <property name="car" ref="car"/>
        <property name="office" ref="office" />
    </bean>
    <bean id="office" class="com.baobaotao.Office">
        <property name="officeNo" value="002"/>
    </bean>
    <bean id="car" class="com.baobaotao.Car" scope="singleton">
        <property name="brand" value=" 紅旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>


使用 @Autowired 註釋spa

Spring 2.5 引入了 @Autowired 註釋,它能夠對類成員變量、方法及構造函數進行標註,完成自動裝配的工做。來看一下使用@Autowired 進行成員變量自動注入的代碼:code

package com.baobaotao;
import org.springframework.beans.factory.annotation.Autowired;

public class Boss {

    @Autowired
    private Car car;

    @Autowired
    private Office office;

    …
}


Spring 經過一個 BeanPostProcessor@Autowired 進行解析,因此要讓@Autowired 起做用必須事先在 Spring 容器中聲明AutowiredAnnotationBeanPostProcessor Bean。xml

讓 @Autowired 註釋工做起來接口

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- 該 BeanPostProcessor 將自動起做用,對標註 @Autowired 的 Bean 進行自動注入 -->
    <bean class="org.springframework.beans.factory.annotation.
        AutowiredAnnotationBeanPostProcessor"/>

    <!-- 移除 boss Bean 的屬性注入配置的信息 -->
    <bean id="boss" class="com.baobaotao.Boss"/>
 
    <bean id="office" class="com.baobaotao.Office">
        <property name="officeNo" value="001"/>
    </bean>
    <bean id="car" class="com.baobaotao.Car" scope="singleton">
        <property name="brand" value=" 紅旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>

這樣,當 Spring 容器啓動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中全部 Bean,當發現 Bean 中擁有@Autowired 註釋時就找到和其匹配(默認按類型匹配)的 Bean,並注入到對應的地方中去。

按照上面的配置,Spring 將直接採用 Java 反射機制對 Boss 中的 caroffice 這兩個私有成員變量進行自動注入。因此對成員變量使用@Autowired 後,您大可將它們的 setter 方法(setCar()setOffice())從 Boss 中刪除。

將 @Autowired 註釋標註在 Setter 方法上

package com.baobaotao;

public class Boss {
    private Car car;
    private Office office;

     @Autowired
    public void setCar(Car car) {
        this.car = car;
    }
 
    @Autowired
    public void setOffice(Office office) {
        this.office = office;
    }
    …
}

這時,@Autowired 將查找被標註的方法的入參類型的 Bean,並調用方法自動注入這些 Bean。而下面的使用方法則對構造函數進行標註。

將 @Autowired 註釋標註在構造函數上

                package com.baobaotao;

public class Boss {
    private Car car;
    private Office office;
 
    @Autowired
    public Boss(Car car ,Office office){
        this.car = car;
        this.office = office ;
    }
 
    …
}

因爲 Boss() 構造函數有兩個入參,分別是 caroffice@Autowired 將分別尋找和它們類型匹配的 Bean,將它們做爲Boss(Car car ,Office office) 的入參來建立Boss Bean。

@Resource

@Resource 的做用至關於 @Autowired,只不過 @Autowired 按 byType 自動注入,@Resource 默認按 byName 自動注入罷了。@Resource 有兩個屬性是比較重要的,分別是 name 和 type,Spring 將@Resource 註釋的 name 屬性解析爲 Bean 的名字,而 type 屬性則解析爲 Bean 的類型。因此若是使用 name 屬性,則使用 byName 的自動注入策略,而使用 type 屬性時則使用 byType 自動注入策略。若是既不指定 name 也不指定 type 屬性,這時將經過反射機制使用 byName 自動注入策略。

Resource 註釋類位於 Spring 發佈包的 lib/j2ee/common-annotations.jar 類包中,所以在使用以前必須將其加入到項目的類庫中。來看一個使用@Resource 的例子:


通常狀況下,咱們無需使用相似於 @Resource(type=Car.class) 的註釋方式,由於 Bean 的類型信息能夠經過 Java 反射從代碼中獲取。

要讓 JSR-250 的註釋生效,除了在 Bean 類中標註這些註釋外,還須要在 Spring 容器中註冊一個負責處理這些註釋的 BeanPostProcessor

<bean 
  class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

@PostConstruct 和 @PreDestroy

Spring 容器中的 Bean 是有生命週期的,Spring 容許在 Bean 在初始化完成後以及 Bean 銷燬前執行特定的操做,您既能夠經過實現 InitializingBean/DisposableBean 接口來定製初始化以後 / 銷燬以前的操做方法,也能夠經過 <bean> 元素的 init-method/destroy-method 屬性指定初始化以後 / 銷燬以前調用的操做方法。

JSR-250 爲初始化以後/銷燬以前方法的指定定義了兩個註釋類,分別是 @PostConstruct 和 @PreDestroy,這兩個註釋只能應用於方法上。標註了 @PostConstruct 註釋的方法將在類實例化後調用,而標註了 @PreDestroy 的方法將在類銷燬以前調用。

package com.baobaotao;

import javax.annotation.Resource;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Boss {
    @Resource
    private Car car;

    @Resource(name = "office")
    private Office office;

    @PostConstruct
    public void postConstruct1(){
        System.out.println("postConstruct1");
    }

    @PreDestroy
    public void preDestroy1(){
        System.out.println("preDestroy1"); 
    }
    …
}

您只須要在方法前標註 @PostConstruct@PreDestroy,這些方法就會在 Bean 初始化後或銷燬以前被 Spring 容器執行了。

咱們知道,無論是經過實現 InitializingBean/DisposableBean 接口,仍是經過 <bean> 元素的init-method/destroy-method 屬性進行配置,都只能爲 Bean 指定一個初始化 / 銷燬的方法。可是使用@PostConstruct@PreDestroy 註釋卻能夠指定多個初始化 / 銷燬方法,那些被標註 @PostConstruct@PreDestroy 註釋的方法都會在初始化 / 銷燬時被執行。

相關文章
相關標籤/搜索