Spring annotation中,@resource如何找到實現類的
此前有一個疑問:
@Resource
private TestDAO testDAO;
這樣的一句話,Spring怎麼找到TestDAOImpl,使其成為 private TestDAO testDAO = new TestDAOImpl();
1.先從Bean注入說起,談談注入的裝配型別
Spring auto-wire的 五種方式:
1:no 預設的方式是不進行自動裝配,通過手工設定ref 屬性來進行裝配bean
2:byName 通過引數名 自動裝配,如果一個bean的name 和另外一個bean的 property 相同,就自動裝配。
3:byType 通過引數的資料型別自動自動裝配,如果一個bean的資料型別和另外一個bean的property屬性的資料型別相容,就自動裝配
4:construct
5:auto detect 如果有預設的構造方法,通過 construct的方式自動裝配,否則使用 byType的方式自動裝配。用於spring2.5 ,spring3.0測試不通過,估計是廢棄了。 一: auto-wire : no(預設方式)
首先定義測試需要的類:
package com.myapp.core.autowire; public class Book { public String toString(){ return "I'm a book, read me......"; } }
package com.myapp.core.autowire; public class Person { private Book book; public Person(Book book){ this.book= book; } public void setBook(Book book){ this.book = book; } public String toString(){ return "I'm a person I want to read a book "+ book; } public Person(){ } }
<?xml version="1.0" encoding="UTF-8"?>
http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="Index of /schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- more bean definitions for data access objects go here -->
<bean id="person" class="com.myapp.core.autowire.Person">
<property name="book" ref="book" />
</bean>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
</beans>
編寫測試類:
package com.myapp.core.autowire;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("resource/autowire.xml");
Person person = (Person)context.getBean("person");
System.out.println(person.toString());
}
}
測試結果:
I'm a person I want to read a book I'm a book, read me......
二:通過byName 自動裝配:
修改配置檔案如下:
在這個例子中通過bean的屬性名自動裝配;因為這個
person bean的屬性 book和配置檔案中id為book的名字相同,所以Spring將通過setBook(Book book)自動裝配。
<!-- byName -->
<bean id="person" class="com.myapp.core.autowire.Person" autowire="byName">
</bean>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
執行測試類:依然得到如上測試結果。
三:通過byType自動裝配:
在這個例子中通過bean的屬性名的型別進行自動裝配;因為 person bean屬性 book的型別和配置檔案中id為book的型別相同,。所以spring通過setBook(Book book)自動裝配。
修改配置檔案如下;
<!-- byType -->
<bean id="person" class="com.myapp.core.autowire.Person" autowire="byType"/>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
四:通過construct自動裝配:
通過構造方法的引數的資料型別進行自動裝配,在這個例子中因為person的構造方法引數是Book型別,和配置檔案中的id為book的型別相同,所以spring通過Person(Book book)構造方法進行自動裝配。
修改配置檔案如下:
[html]
<!-- construct -->
<bean id="person" class="com.myapp.core.autowire.Person" autowire="constructor"/>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
五:通過 autodetect 自動裝配:
Spring 3.0配置的xml不能用於autodetect,spring3.0應該是去掉了這個功能,改用spring2.5配置可以順利通過測試,
首先使用construct的自動裝配形式進行裝配,如果沒有construct就通過 byType的形式進行自動裝配。<beans
http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="Index of /schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="person" class="com.myapp.core.autowire.Person" autowire="autodetect" />
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
</beans>
測試結果:
I'm a person I want to read a book I'm a book, read me......
一:我們通過@Resource指明瞭name屬性
public interface UserDao{
....
}
@Repository("userDao")
public class UserDaoImpl implements UserDao{
...
}
public class UserServiceImpl{
private UserDao userDao;
@Resource("userDao") //通過@Repository("userDao")註解找到UserServiceImpl類的
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
....
....
}
或
Resource("userDao")
private UserDao userDao;
此處是通過byName自動裝配的
一:我們通過@Resource沒有指明name屬性,此處就是剛開始的問題
private UserDao userDao;
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
或
@Resource
private UserDao userDao;
此處通過ByType自動裝配 其實ByType自動裝配是通過 public class UserDaoImpl implements UserDao, 知道UserDao子類為UserDaoImpl,從而找到UserDaoImpl 類的 所以通過ByType自動裝配時,一個介面的實現方法只有一個,下面舉個栗子說明一下 三:通過ByType自動裝配時,注意事項(一個介面的實現方法只有一個)
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
xml檔案裡,沒有一個名字為userDao的bean
<bean id="userDaoImpl" class="com.fz.annotation.dao.impl.UserDaoImpl">
</bean>
<bean id="userDaoImpl1" class="com.fz.annotation.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.fz.annotation.service.UserService">
</bean>
此時測試的時候會報錯,因為預設按byName,此時是沒有名字為userDao的bean的,所以再次按byType,但是byType會出現兩個相同型別的bean
所以會報錯。
此時,刪掉一個bean的定義
<bean id="userDaoImpl1" class="com.fz.annotation.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.fz.annotation.service.UserService">
</bean>
再次測試的時候就正常,不會報錯。
原因:
ByType自動裝配是通過 public class UserDaoImpl implements UserDao, 知道UserDao子類為UserDaoImpl,從而找到UserDaoImpl 類的 但UserDao有兩個子類時,spring不知道注入哪一個子類,所以會報錯例項源自:
https://www.zhihu.com/question/39361250
http://www.cnblogs.com/meet/p/4758211.html