1. 程式人生 > >Spring annotation中,@resource如何找到實現類的

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

構造方法中的引數通過byType的形式,自動裝配。
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......

2.當我們用註釋注入時
一:我們通過@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