spring的注入

 

1 可能遇到的問題:

異常信息 NoSuchBeanDefinitionException: No matching bean of type [...]或是NoSuchBeanDefinitionException: No unique bean of type [...] 這二者具體區別暫不深究,但究其緣由都是由於找不到某類型的bean,後面再講。java

異常信息 expected single matching bean but found 2,很好理解,以前是找不到,如今是找到不止一個,spring不知道該怎麼辦了。spring

...待補充post

 

2 注入和注出

     這是未經考證的說法,我認爲區分爲這二者以後比較容易理解注入問題。嚴格來說注入和注出關系被以各類方式描述在了beanDefinition裏面,相似於消費者和生產者。他們的行爲每每發生在spring容器初始化時,除非指定爲了prototype。ui

     排查問題時從這兩個角度來看,注入是否是不對,注出是否是不對。spa

 

2.1 常見的注出方式

1. 咱們必需要了解最簡單直接的方式,即prototype

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" />

  就這種方式而言也另有工廠方法方式,其中還分爲靜態工廠以及實例工廠,不細講component

 

2. 在spring後續引入註解後,在對類施加@Service @Component @Controller @Repository這四種註解(他們在注出上做用同樣),並配置包掃描:xml

<context:component-scan base-package="com.mypackage"/>

  同時配置註解的類要在包掃面的路徑以內。註解注出的bean默認的id和name是類名第一個字母改成小寫blog

 

2.2 常見的注入方式

  注入指的是通知spring你的bean對哪些bean擁有實例或稱依賴,須要spring作「填充」。
繼承

2.2.1.顯式注入:setter注入(還有constructor注入,與此相似):  

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource">
       <ref>dataSource</ref>
    </property>
</bean>

  setter注入須要有對應的setter方法,請注意駝峯命名,不然拋出找不到setter的異常。constructor注入須要對應的構造方法。

 

2.2.2.自動裝配

  default-autowire="byName/byType"

  特別注意,這個東西和@autowire沒有半毛錢關係,通常出如今spring文件頭,即<beans>標籤內。這個設置會智能的掃描每一個bean有哪些setter方法,並添加相似第一條的property。也就是說有此配置後就不須要上面的<property></property>標籤了。不一樣之處在於顯式配置可自由指定所需的bean,default-autowire只有根據名稱、類型來匹配。

 

2.2.3.註解注入

  首先要啓動註解注入,主要由AutowiredAnnotationBeanPostProcessor、 CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor以及requiredAnnotationBeanPostProcessor這四個類來負責檢測註解並實現注入的,因此spring容器須要獲得這幾個類的bean,這裏有兩種方式:

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

 

  使用到哪一個註解就註冊對應的PostProcessor,假如使用autowired,就用這個就能夠了。其餘的具體對應關係請自行研究。

  • 懶漢式
<context:annotation-config /> 

  這個配置將隱式地向 Spring 容器註冊AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor以及equiredAnnotationBeanPostProcessor這 4 個 BeanPostProcessor。而上述的 component-scan該配置項其實也包含了自動注入上述processor的功能,所以當使用 <context:component-scan/> 後,就能夠將 <context:annotation-config/> 移除了。這是由於前者默認包含着這樣一個屬性:annotation-config="true",假如咱們將其顯式指定爲false,那麼就要另外添加<context:annotation-config/>配置。

 


啓動註解注入以後,固然要使用註解:

@autowired

  @autowired 注入的註解,默認是按type注入,但能夠用@Qualifier("abc")改成byname。

  使用方法:  
    1. 寫在setter中如:
  
     @Autowired 
   setAbc(@Qualifier("abc")Abc abc)

  事實證實,寫在方法前面的autowire能夠無視方法名,如    

     @Autowired
     public void aaa(QuestionMarkDao questionMarkDao) {
          super.setBaseDao(questionMarkDao);
     }

  這樣,和@postConstruct註解就相對比較接近了,不一樣在於前者能夠帶參數,參數會自動從容器中找對應的bean

   
2.也可寫在變量前,能夠省略setter,如 
  
   @Autowired @Qualifier("abc")
  MyClass  myClass;

 

@Resource 

  按name來注入的註解,找不到的時候嘗試按type注入。byName指的是優先byName,若是找不到與屬性名稱相同的bean時再按照type進行查找。這裏就會出現上面講的兩個異常了,第一種是沒找到相同名字、也沒有相同類型( No unique bean of type );第二種是有相同名字,可是類型不一樣(……);第三種是沒有找到相同名字,可是相同類型的有多個( expected single matching bean but found 2)

  小細節,在子類中須要注入基類的某個屬性a還不能用resource注入,由於假如使用子類,那麼沒有問題使用的是子類版本的屬性a,假如代碼運行到基類的代碼,調用到a屬性時,這時候使用的是基類的a,注入就沒有意義了,容易nullpointer。因此在繼承關係中有屬性隱藏的時候,最好使用顯式的注入方式,選擇只注入基類,也能夠只注入子類,或是都注入。
 
  使用方法(能夠省略setter):
 
@Resource
MyClass myClass

@Resource(name="otherName")
MyClass myClass

  


other stuff:

 
同id的bean:
  兩個bean擁有相同的id:在同一個文件中會報錯的。可是若是經過<import,來自於不一樣的xml文件不會報錯,spring會根據加載順序來選擇後一個bean,第一個bean直接無視。
不一樣spring文件的default-autowire:
  是否會互相影響,我還沒研究過,有人知道請告訴我
p標籤:
  p標籤就是property
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />

  須要引入xmlns以及schemaLocation

value和ref的區別:

  前者是注入字符串值,後者注入容器內的bean(id爲ref值的bean)

相關文章
相關標籤/搜索