spring的依赖注入---接口类直接调用实现类的方法

qishenghui 2013-03-20 04:31:34
先看一段代码
假设你编写了两个类,一个是人(Person),一个是手机(Mobile)。
人有时候需要用手机打电话,需要用到手机的dialUp方法。
传统的写法是这样:

Java code

public class Person{
public boolean makeCall(long number){
Mobile mobile=new Mobile();
return mobile.dialUp(number);
}
}


也就是说,类Person的makeCall方法对Mobile类具有依赖,必须手动生成一个新的实例new Mobile()才可以进行之后的工作。
依赖注入的思想是这样,当一个类(Person)对另一个类(Mobile)有依赖时,不再该类(Person)内部对依赖的类(Moblile)进行实例化,而是之前配置一个beans.xml,告诉容器所依赖的类(Mobile),在实例化该类(Person)时,容器自动注入一个所依赖的类(Mobile)的实例。
接口:

Java code

public Interface MobileInterface{
public boolean dialUp(long number);
}


Person类:

Java code

public class Person{
private MobileInterface mobileInterface;
public boolean makeCall(long number){
return this.mobileInterface.dialUp(number);
}
public void setMobileInterface(MobileInterface mobileInterface){
this.mobileInterface=mobileInterface;
}
}
在xml文件中配置依赖关系

Java code
<bean id="person" class="Person">
<property name="mobileInterface">
<ref local="mobileInterface"/>
</property>
</bean>
<bean id="mobileInterface" class="Mobile"/>
这样,Person类在实现拨打电话的时候,并不知道Mobile类的存在,它只知道调用一个接口MobileInterface,而MobileInterface的具体实现是通过Mobile类完成,并在使用时由容器自动注入。
---------------------------------以上是复制过来的代码

Person类中有这个方法----mobileInterface.dialUp(number)。mobileInterface是个接口,怎么可以直接调用该接口实现类的方法?还有其怎么依赖注入的?请大侠拔刀相助啊,急......
...全文
12435 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
shark_二等 2013-04-08
  • 打赏
  • 举报
回复
注入的是实现类
Yalonexm 2013-03-26
  • 打赏
  • 举报
回复
引用 11 楼 qishenghui 的回复:
引用 5 楼 Yalonexm 的回复:这样在person 中调用makeCall的时候,实际上就是调用了mobile的makeCall方法了。 这里说错 在person中调用mobileInterface.dialUp(number)的时候,实际上是调用了mobile的dialUp(number)方法了 bean 的配置是不是就是new一个类? ……
可以这样说,但是远远不只有这么简单而已,他还维护bean与bean之间的关系,为了使程序变得灵活,spring推崇的是"面向接口编程"。
jerry在魔都 2013-03-25
  • 打赏
  • 举报
回复
bean配置就是让容器要来管理一个Mobile的对象,spring容器会帮你来创建这个对象实例,不过spring 创建对象用的是反射来实现的,大概就是Class clazz = Class.forName("Mobile"); Object obj = clazz.newInstance(); 这个样子
qishenghui 2013-03-25
  • 打赏
  • 举报
回复
引用 5 楼 Yalonexm 的回复:
这样在person 中调用makeCall的时候,实际上就是调用了mobile的makeCall方法了。 这里说错 在person中调用mobileInterface.dialUp(number)的时候,实际上是调用了mobile的dialUp(number)方法了
bean 的配置是不是就是new一个类?
qishenghui 2013-03-25
  • 打赏
  • 举报
回复
引用 8 楼 justsmilence 的回复:
引用 4 楼 Yalonexm 的回复:mobileInterface.dialUp(number)。mobileInterface是个接口,怎么可以直接调用该接口实现类的方法? Java对类的定型是通过“上溯造型”这样就能确保不会丢失精度,保证类型的统一。这也是接口的一个好处。 在进行方法调用的时候,具体调用的是什么类的方法是通过动态绑定的。 也就是说虽然mo……
bean 的配置是不是就是new一个类?
qishenghui 2013-03-25
  • 打赏
  • 举报
回复
引用 1 楼 aihu_2013 的回复:
<bean id="mobileInterface" class="Mobile"/> 注入的是实现了mobileInterface接口的子类,调用的当然是子类重写的dialUp方法
bean 的配置是不是就是new一个类?
  • 打赏
  • 举报
回复
引用 4 楼 Yalonexm 的回复:
mobileInterface.dialUp(number)。mobileInterface是个接口,怎么可以直接调用该接口实现类的方法? Java对类的定型是通过“上溯造型”这样就能确保不会丢失精度,保证类型的统一。这也是接口的一个好处。 在进行方法调用的时候,具体调用的是什么类的方法是通过动态绑定的。 也就是说虽然mobileInterface.dialUp……
很详细 ,学习到了
Mr_Oyeah 2013-03-21
  • 打赏
  • 举报
回复
第一个问题:百度下“java 向上转型” 接口为父类 ,赋值的为子类,用父类调用,其实相当于还是调用子类的方法。 第二个问题:通过java反射机制,获取到person的属性,同时根据配置文件中所配置的依赖类实例化给person的属性。
tianma630 2013-03-21
  • 打赏
  • 举报
回复
不使用反射的话,代码应该是这样的 private MobileInterface mobileInterface = new Mobile(); 反射相当于帮你实现了new Mobile(); 原理是用java反射实现的
Yalonexm 2013-03-20
  • 打赏
  • 举报
回复
这样在person 中调用makeCall的时候,实际上就是调用了mobile的makeCall方法了。 这里说错 在person中调用mobileInterface.dialUp(number)的时候,实际上是调用了mobile的dialUp(number)方法了
Yalonexm 2013-03-20
  • 打赏
  • 举报
回复 1
mobileInterface.dialUp(number)。mobileInterface是个接口,怎么可以直接调用该接口实现类的方法? Java对类的定型是通过“上溯造型”这样就能确保不会丢失精度,保证类型的统一。这也是接口的一个好处。 在进行方法调用的时候,具体调用的是什么类的方法是通过动态绑定的。 也就是说虽然mobileInterface.dialUp(number)表面上看是调用的接口的方法,这样会出错。但是在运行期间mobileInterface一般会被动态绑定到一个实现类的,如果没绑定这样也确实会出错。 下面看看你的beans.xml的配置 <bean id="person" class="Person"> <property name="mobileInterface"> <ref local="mobileInterface"/> </property> </bean> <bean id="mobileInterface" class="Mobile"/> 这里显然在最后个bean中为mobileInterface指定的是一个实现类Mobile。也就是说Mobile的对象调用dialUp(number)是具有意义的,而且可行的。spring在这个过程中“偷天换柱”的把接口动态绑定到了Mobile的对象上。也就是说mobileInterface.dialUp(number)在调用时实际上调用的是Mobile对象的dialUp(number)方法了。这样就可以显示正常结果了。 还有其怎么依赖注入的? 这个就简单了,用的是java的反射机制。在spring配置文件加载期间,spring会用反射机制给bean中配置的对象属性注入属性值。 他是怎么注入的呢?看配置文件: <bean id="person" class="Person"> <property name="mobileInterface"> <ref local="mobileInterface"/> </property> </bean> <bean id="mobileInterface" class="Mobile"/> 第一句 <bean id="person" class="Person"> 告诉spring我们这里有个bean他的类是Person,我给他的唯一id是person,此时spring会new一个Person对象,放在结果的Map中,对应的key就是你这里配置的id。所以你可以get(id)的形式来获取对象。 第二句 <property name="mobileInterface">说明我前面new的Person对象中有一个属性是mobileInterface 第三句<ref local="mobileInterface"/>是给属性赋值(调用对象的set方法,如果没有set方法会报错),他指向一个引用,看到这里spring会延迟赋值(你可以这样认为) 第四句 <bean id="mobileInterface" class="Mobile"/>创建一个id是mobileInterface的Mobile对象,这样我们再回到第三句就可以通过id进行对应的引用了。也就是说第三句的功能就实现了,把Mobile对象赋值给了Person对象的mobileInterface属性。严格说就是id为person的Person对象的mobileInterface属性指向了id为mobileInterface的Mobile对象(这里的一系列操作是spring帮我们完成的,对属性赋值需要调用属性的set方法)。有点绕~ 好好理解。 上面就相当于 Person person = new Person(); Mobile mobile = new Mobile(); person .setMobileInterface(mobile); 这样在person 中调用makeCall的时候,实际上就是调用了mobile的makeCall方法了。 还有为什么Person 类里面要调用接口的的方法呢mobileInterface.dialUp(number); 先来假设下:你有很多手机(诺基亚,Iphone,三星,华为。。。。) 他们打电话的时候拨号的方式不一样,如果你这里写成一个具体的手机的dialUp方法。比如说 诺基亚.dialUp(number),看上去很好。没有理解问题,但是如果你换手机了呢?你突然发财了换了Iphone 那你岂不是要改变下这个类换成 Iphone.dialUp(number)?...如此下去你岂不是每换一次手机就要改下这个类。很麻烦是不是? 其实你研究会发现 这些手机不管是什么牌子的都能打电话(都具有dialUp(number)方法),只是拨号的方式不一样而已,但是功能都是为了打电话。何不把这个功能提取出来?对了,你可以这样做。我现在知道我可以用手机打电话,具体怎么打我不管他,在我打电话的时候我再决定。(也就是前面提到的在真正的运行期的时候来动态绑定,看具体调用什么对象的方法)。是不是一举N得?以后我都不需要改变这个类了。真正做到了以不变应万变。
dracularking 2013-03-20
  • 打赏
  • 举报
回复
所以说这样起名很不科学,给你了误导 private MobileInterface mobileInterface; mobileInterface最好改为mobileinstance或mobile,表示注入的是MobileInterface的一个实现
-AJ- 2013-03-20
  • 打赏
  • 举报
回复
@Serivce + interface
aihu_2013 2013-03-20
  • 打赏
  • 举报
回复
<bean id="mobileInterface" class="Mobile"/> 注入的是实现了mobileInterface接口的子类,调用的当然是子类重写的dialUp方法

81,092

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧