Spring註解註解解析

咱們在使用spring的時候常常會用到這些註解,那麼這些註解到底有什麼區別呢。咱們先來看代碼css

一樣分三層來看:java

Action 層:spring

package com.ulewo.ioc;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;@Controllerpublic class IocAction {
    @Autowired    private IocService service;
    
    public void add(){
        service.add();
    }
}

service層:(service就直接定義類了,沒有定義接口,定義接口也是同樣的)
app

package com.ulewo.ioc;import javax.annotation.Resource;import org.springframework.stereotype.Service;@Servicepublic class IocService {
    @Resource    private IIocDao iocDao;
    public void add(){
        iocDao.add();
    }
}

Dao層
測試

先定義一個接口
spa

package com.ulewo.ioc;public interface IIocDao {
    public void add();
}

而後實現類:
.net

package com.ulewo.ioc;import org.springframework.stereotype.Repository;@Repositorypublic class IocDao implements IIocDao{
    public void add(){
        System.out.println("調用了dao");
    }
}

而後spring的配置,這個配置就很簡單了,由於是基於註解的,咱們不須要再xml中來定義不少
code

applicationContext.xmlcomponent

<?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:jee="http://www.springframework.org/schema/jee"   xmlns:tx="http://www.springframework.org/schema/tx"   xmlns:context="http://www.springframework.org/schema/context"   xmlns:aop="http://www.springframework.org/schema/aop"   xmlns:task="http://www.springframework.org/schema/task"   xsi:schemaLocation="http://www.springframework.org/schema/beans 
                       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
                       http://www.springframework.org/schema/tx 
                       http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
                       http://www.springframework.org/schema/jee 
                       http://www.springframework.org/schema/jee/spring-jee-3.2.xsd 
                       http://www.springframework.org/schema/context 
                       http://www.springframework.org/schema/context/spring-context-3.2.xsd
                       http://www.springframework.org/schema/aop 
                       http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                       http://www.springframework.org/schema/task 
                       http://www.springframework.org/schema/task/spring-task-3.2.xsd">    <context:annotation-config />        <context:component-scan base-package="com.ulewo.ioc" >    </context:component-scan>  </beans>

讓spring自動掃描包就好了。orm

而後是咱們的測試類:

IocTest:

package com.ulewo.ioc;import junit.framework.TestCase;import org.springframework.beans.factory.BeanFactory;import org.springframework.context.support.ClassPathXmlApplicationContext;public class IocTest extends TestCase{
    
    public void testIoc(){
        BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
        IocAction action = factory.getBean("iocAction", IocAction.class);
        action.add();
    }
}

運行後,咱們會發現 控制檯打印:調用了dao

@Component、@Repository、@Service、@Controller @Resource、@Autowired、@Qualifier 

這幾個基本都用到了 除了 @Component  @Qualifier

咱們觀察會發現@Repository、@Service、@Controller 這幾個是一個類型,其實@Component 跟他們也是一個類型的

Spring 2.5 中除了提供 @Component 註釋外,還定義了幾個擁有特殊語義的註釋,它們分別是:@Repository、@Service和 @Controller 其實這三個跟@Component 功能是等效的


@Service用於標註業務層組件(咱們一般定義的service層就用這個)

@Controller用於標註控制層組件(如struts中的action)

@Repository用於標註數據訪問組件,即DAO組件

@Component泛指組件,當組件很差歸類的時候,咱們可使用這個註解進行標註。


這幾個註解是當你須要定義某個類爲一個bean,則在這個類的類名前一行使用@Service("XXX"),就至關於講這個類定義爲一個bean,bean名稱爲XXX; 這幾個是基於類的,咱們能夠定義名稱,也能夠不定義,不定義會默認以類名爲bean的名稱(類首字母小寫)。


而後咱們在看後面的幾個註解

@Resource、@Autowired、@Qualifier

當須要在某個類中定義一個屬性,而且該屬性是一個已存在的bean,要爲該屬性賦值咱們就用着三個。咱們看上面的代碼能夠看到這三個都是定義在一個屬性上的,好比

@Resourceprivate IIocDao iocDao;
@Autowiredprivate IocService service;

那這幾個到底有什麼區別呢?

咱們先看@Resource,它是javax.annotation.Resource; 這個包中,也就是說是javaEE中的,並非spring中的

並且@Resource("xxx") 是能夠定義bean名稱的,就是說我這個屬性要用那個bean來賦值。


@Autowired,它是org.springframework.beans.factory.annotation.Autowired 是這個包中,它是spring的包。

並且它沒有@Autowired("xxx"),那我要爲這個bean定義名稱怎麼辦這個時候能夠用@Qualifier("xxx") 這個也是spring中的。這個xxx定義bean名稱有什麼用呢?咱們回頭看下剛纔的代碼。

在IIocDao 這個接口中,咱們定義的實現類IocDao 只有一個,好那麼咱們再定義一個實現類:

package com.ulewo.ioc;import org.springframework.stereotype.Repository;@Repositorypublic class IocDao2 implements IIocDao{
    public void add(){
        System.out.println("調用了dao2");
    }
}

其餘不變,咱們再運行:testIoc(),控制檯打印出 調用了dao,因此在service層中

@Resource
private IIocDao iocDao;

這個iocDao 注入的是IocDao 這個實現。奇怪了,它怎麼知道我要調用哪一個實現呢?

好咱們修改一下,把 private IIocDao iocDao;改一下,改爲 private IIocDao iocDaox 把屬性名改一下,再運行,會報錯:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.ulewo.ioc.IIocDao] is defined: expected single matching bean but found 2: iocDao,iocDao2

錯誤很明顯啊,有兩個bean iocDao和iocDao2,可是咱們的是iocDaox因此找不到了。因此能夠看出來在用 @Repository註解來生成bean的時候,若是沒有定義名稱那麼就會根據類名來生成。因此咱們要調用第二個實現的時候能夠 定義爲private IIocDao iocDao2 。咱們再運行:調用了dao2,因此能夠根據屬性名來區分,到底注入那個bean。可是有的人說,我不想定義bean名稱跟類實現同樣,我要定義其餘的,那怎麼玩呢,方法有2種:


第一種:咱們在生成bean的時候就給bean定義個名稱 

@Repository("myIocDao")
public class IocDao implements IIocDao{
    public void add(){
        System.out.println("調用了dao");
    }
}

固然@Service是同樣的,這樣就把這個實現定義爲myIocDao了,而不是默認的類名 iocDao。

那麼咱們在使用這個bean的時候就要這麼定義了:

@Resource
private IIocDao myIocDao;

運行 輸出:調用了dao

若是你這裏不是用的 myIocDao,你又多加了一個x,成了myIocDaox,你運行會是這樣的:

 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.ulewo.ioc.IIocDao] is defined: expected single matching bean but found 2: myIocDao,iocDao2

因此,要自定義bean的名稱能夠在類註解的時候指定。


第二種:在注入bean的時候指定名稱:

先看@Resource

咱們這麼定義下:

@Resource(name="iocDao")
private IIocDao xx;

注意:

@Repository
public class IocDao implements IIocDao{
    public void add(){
        System.out.println("調用了dao");
    }
}

這裏仍是用會默認的,也就是這個實現對應的是 iocDao這bean。若是你要爲這個類指定別名bean,@Repository("myIocDao"),那@Resource(name="myIocDao") 就要這麼寫了。就是這裏的name要跟實現類對應的bean名稱保持一致。private IIocDao xx; 這個屬性名就隨便寫了。

運行:調用了dao

若是用Autowired就要這麼寫了

@Autowired
@Qualifier("iocDao")
private IIocDao xx;

由於Autowired 不能像Resource 那樣帶個參數指定一個name,就要用Qualifier來指定了。


並且還能夠這麼用

@Resource
@Qualifier("iocDao")
private IIocDao xx;

等同於

@Resource(name="iocDao")
private IIocDao xx;


記住一點:@Resource的做用至關於@Autowired,只不過@Autowired按byType自動注入,若是發現找到多個bean,則,又按照byName方式比對,若是還有多個,則報出異常 而@Resource默認按 byName自動注入罷了。其實spring註解,最經常使用的仍是根據名稱,根據類型啊,構造方法啊,用的很是少。因此在多個實現的時候咱們定義好bean的名稱就行,就不會錯亂。

相關文章
相關標籤/搜索