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。
@Autowired setAbc(@Qualifier("abc")Abc abc)
事實證明,寫在方法前面的autowire可以無視方法名,如
@Autowired public void aaa(QuestionMarkDao questionMarkDao) { super.setBaseDao(questionMarkDao); }
這樣,和@postConstruct注解就相對比較接近了,不同在於前者可以帶參數,參數會自動從容器中找對應的bean
@Autowired @Qualifier("abc") MyClass myClass;
@Resource
按name來注入的注解,找不到的時候嘗試按type注入。byName指的是優先byName,如果找不到與屬性名稱相同的bean時再按照type進行查找。這里就會出現上面講的兩個異常了,第一種是沒找到相同名字、也沒有相同類型( No unique bean of type );第二種是有相同名字,但是類型不同(……);第三種是沒有找到相同名字,但是相同類型的有多個( expected single matching bean but found 2)
@Resource MyClass myClass @Resource(name="otherName") MyClass myClass
other stuff:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource" />
需要引入xmlns以及schemaLocation
value和ref的區別:
前者是注入字符串值,后者注入容器內的bean(id為ref值的bean)