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






  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值