天天看點

@Autowired 與@Resource之争

1、@Autowired與@Resource都可以用來裝配bean. 都可以寫在字段上,或寫在setter方法上。

2、@Autowired預設按類型裝配(這個注解是屬于spring的)

預設情況下必須要求依賴對象必須存在,如果要允許null值,可以設定它的required屬性為false,如:

@Autowired(required=false) ,如果我們想使用名稱裝配可以結合@Qualifier注解進行使用,如下:

@Autowired() @Qualifier("baseDao")    
private BaseDao baseDao;

           

3、@Resource 是JDK1.6支援的注解,預設按照名稱進行裝配

名稱可以通過name屬性進行指定,

如果沒有指定name屬性

  • 當注解寫在字段上時,預設取字段名,按照名稱查找
  • 如果注解寫在setter方法上預設取屬性名進行裝配
  • 當找不到與名稱比對的bean時才按照類型進行裝配

但是需要注意的是,如果name屬性一旦指定,就隻會按照名稱進行裝配。

@Autowired 與@Resource之争

隻不過注解處理器我們使用的是Spring提供的,是一樣的,無所謂解耦不解耦的說法,兩個在便利程度上是等同的。

@Resource(name="baseDao")    
private BaseDao baseDao; 

           

byName 通過參數名 自動裝配,如果一個bean的name 和另外一個bean的 property 相同,就自動裝配。

byType 通過參數的資料類型自動自動裝配,如果一個bean的資料類型和另外一個bean的property屬性的資料類型相容,就自動裝配

我們可以通過 @Autowired / @Resource 在 Bean 類中使用自動注入功能,但是 Bean 還是在 XML 檔案中通過 <bean> 進行定義 —— 也就是說,在 XML 配置檔案中定義 Bean,通過@Autowired 或 @Resource 為 Bean 的成員變量、方法入參或構造函數入參提供自動注入的功能。

比如下面的beans.xml

public class Boss {
    private Car car;
    private Office office;
    
   @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}

           
<?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-2.5.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config/> 

    <bean id="boss" class="com.sss.Boss"/>
    <bean id="office" class="com.sss.Office">
        <property name="officeNo" value="001"/>
    </bean>
    <bean id="car" class="com.sss.Car" scope="singleton">
        <property name="brand" value=" 紅旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>

           

定義了三個bean對象,但是沒有了我們書序的ref指向的内容

比如

<?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.sss.Boss">
        <property name="car" ref="car"/>
        <property name="office" ref="office" />
    </bean>
    <bean id="office" class="com.sss.Office">
        <property name="officeNo" value="002"/>
    </bean>
    <bean id="car" class="com.sss.Car" scope="singleton">
        <property name="brand" value=" 紅旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>

           

spring2.5提供了基于注解(Annotation-based)的配置,我們可以通過注解的方式來完成注入依賴。在Java代碼中可以使用 @Resource或者@Autowired注解方式來經行注入。雖然@Resource和@Autowired都可以來完成注入依賴,但它們之間是有區 别的。首先來看一下:

a.@Resource預設是按照名稱來裝配注入的,隻有當找不到與名稱比對的bean才會按照類型來裝配注入;
b.@Autowired預設是按照類型裝配注入的,如果想按照名稱來轉配注入,則需要結合@Qualifier一起使用;
c.@Resource注解是由JDK提供,而@Autowired是由Spring提供

@Resource的方式;
d. @Resource和@Autowired都可以書寫标注在字段或者該字段的setter方法之上

           

2、使用注解的方式,我們需要修改spring配置檔案的頭資訊

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

----------------------PS開始-------------------------------

在基于注解方式配置Spring的配置檔案中,你可能會見到

<context:annotation-config/>

           

這樣一條配置,他的作用是式地向 Spring 容器注冊

AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor

           

這 4 個BeanPostProcessor。

注冊這4個BeanPostProcessor的作用,就是為了你的系統能夠識别相應的注解。

例如:

如果你想使用@Autowired注解,那麼就必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean。傳統聲明方式如下

<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/> 

           

如果想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就必須聲明CommonAnnotationBeanPostProcessor

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

           

如果想使用@PersistenceContext注解,就必須聲明PersistenceAnnotationBeanPostProcessor的Bean。

<bean class="org.springframework.beans.factory.annotation.PersistenceAnnotationBeanPostProcessor"/> 

           

如果想使用 @Required的注解,就必須聲明RequiredAnnotationBeanPostProcessor的Bean。

同樣,傳統的聲明方式如下:

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/> 

           

一般來說,這些注解我們還是比較常用,尤其是Antowired,在自動注入的時候更是經常使用,是以如果總是需要按照傳統的方式一條一條配置顯得有些繁瑣和沒有必要,于是spring給我們提供<context:annotation-config/>的簡化配置方式,自動幫你完成聲明。

不過,呵呵,我們使用注解一般都會配置掃描包路徑選項

<context:component-scan base-package=”XX.XX”/>

該配置項其實也包含了自動注入上述processor的功能,是以當使用 <context:component-scan/> 後,就可以将 <context:annotation-config/> 移除

比如:

<context:component-scan base-package="carPoolingController, carPoolingService, carPoolingDao" />

           

就把controller包下 service包下 dao包下的注解全部掃描了

----------------------------------------------PS結束------------------------------

3、修改以上配置檔案的頭資訊後,我們就可以在Java代碼通過注解方式來注入bean,看下面代碼

(1)@Resource

public class StudentService3 implements IStudentService {
    //@Resource(name="studentDao")放在此處也是可行的
    private IStudentDao studentDao;

    private String id;

    public void setId(String id) {
    this.id = id;
    }

           

@Resource(name="studentDao") // 通過此注解完成從spring配置檔案中查找名稱為studentDao的bean來裝配字段studentDao,如果spring配置檔案中不存在 studentDao名稱的bean則轉向按照bean類型進行查找

public void setStudentDao(IStudentDao studentDao) {
        this.studentDao = studentDao;
}
public void saveStudent() {
        studentDao.saveStudent();
        System.out.print(",ID 為:"+id);
}
           

配置檔案添加如下資訊

<bean id="studentDao" class="com.sss.dao.impl.StudentDao"></bean>
<bean id="studentService3" class="com.sss.service.impl.StudentService3"></bean>

           

(2)@Autowired

public class StudentService3 implements IStudentService {
  //@Autowired放在此處也是可行的
  private IStudentDao studentDao;

  private String id;

  public void setId(String id) {
       this.id = id;
   }

           

@Autowired

//通過此注解完成從spring配置檔案中 查找滿足studentDao類型的bean

//@Qualifier("studentDao")則按照名稱經行來查找轉配的

public void setStudentDao(IStudentDao studentDao) {
       this.studentDao = studentDao;
  }

  public void saveStudent() {
       studentDao.saveStudent();
       System.out.print(",ID 為:"+id);
  }
}

           
<bean id="studentDao" class="com.wch.dao.impl.StudentDao"></bean>
<bean id="studentService3" class="com.wch.service.impl.StudentService3" />

           

當我們在xml裡面為類配置注入對象時,會發現xml檔案會越來越臃腫,維護起來很麻煩。這時候我們可以使用注解這種機制來為類配置注入對象。

原生java為我們提供了 javax.annotation.Resource這個注解。

spring架構提供了org.springframework.beans.factory.annotation.Autowired。

一般情況下我們使用 javax.annotation.Resource這個注解,因為這樣我們就能實作和spring架構的解藕(難以認同,因為注解處理器還是Spring提供的)。

@Resource可以作用于字段和函數上。當作用于字段上的時候,如果我們隻是簡單的這樣寫

@Resource
PersonDao  p;

           

這時候spring注入p的過程是

1:查找xml中是否有id為p的元素

2:如果沒有找到,則看是否有name屬性(@Resource name=“”),有則查找name

3:否則查找PersonDao類型的元素

@Resource可作用于set函數上。

@Resource
public void setP(PersonDao p) {
  this.p = p;
}

           

@Autowired注解是根據類型進行查找,比如PersonDao p,他會去xml檔案裡查找類型為PersonDao的元素