spring的注入


 

1 可能遇到的問題:

異常信息 NoSuchBeanDefinitionException: No matching bean of type [...]或是NoSuchBeanDefinitionException: No unique bean of type [...] 這兩者具體區別暫不深究,但究其原因都是因為找不到某類型的bean,后面再講。

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

...待補充

 

2 注入和注出

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

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

 

2.1 常見的注出方式

1. 我們必須要了解最簡單直接的方式,即

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

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

 

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

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

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

 

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)

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM