zoukankan      html  css  js  c++  java
  • java之Spring实现控制反转

    先来复习一下多态吧,简单点讲,就是一个类的引用可以指向其本身以及其子类的对象。

    Like these:

    FatherClass a = new FatherClass();

    FatherClass a = new Son1Class();

    FatherClass a = new Son2Class();

    再来说说接口和其实现类,父类和子类是继承关系(父子关系),接口和实现类的关系与之是有区别的;

    接口中只定义方法,没有方法体,而接口实现类就是负责补充方法体,多个实现类的方法体可以是不同的。

    现在定义一个接口InterfaceDemo和两个实现类Demoimp1、Demoimp2.三个类都有同名方法say();

    InterfaceDemo b = new Demoimp1();

    InterfaceDemo c = new Demoimp2();

    那么b.say()和c.say()是调用了两个不同的方法的。

    说到这,就该轮到Spring闪亮登场了!!!

    1.面向接口的编程

    从上面我们可以看到,我们想要调用某个实现类的say()方法,先要实例化一个这个类的对象,无论是直接实例化

    还是通过引用多态的方式实例化该类对象。

    而面向接口呢,是不显式地实例化这个实现类对象,而是定义一个接口类的对象,然后定义方法去调用接口类对

    象的方法,然后在程序要真正使用这个方法时,先通过setter()方法来声明这个接口类对象具体是指向哪个实现类

    的对象,然后运行这个方法时就会真正调用接口实现类的的方法了(接口和实现类的方法名都相同)。

     1 public class Userservice {
     2     // 定义接口的引用
     3     private UserDao userdao;
     4 
     5     // 定义setter方法,设置接口的引用指向哪个实现类的对象
     6     public void setUserdao(UserDao userdao) {
     7         this.userdao = userdao;
     8     }
     9 
    10     public void useradd(User newuser) {
    11         // 此时的userdao经过spring依赖注入之后已经实现指向特定的接口实现类对象
    12         // 那么调用接口的方法,实际上是调用了特定实现类的方法的
    13         userdao.adduser(newuser);
    14     }
    15 }

    2.依赖注入

    又叫做接口注入,可以看做规定这个接口对象userdao到底要指向哪个实现类的对象,进而实现对何种实现类方法

    的调用。

    以下是beans.xml文件:

    1     <bean id="todo" class="com.eco.daoimp.Usertodo1"></bean>
    2     
    3     <!--定义Userservice类内部接口的引用(userdao)指向具体的实现类对象(Usertodo1) -->
    4     <bean id="userservice" class="com.eco.service.Userservice">
    5         <property name="userdao" ref="todo"></property>
    6     </bean>

    依赖注入有三种方法,在这里只说最常用的setter注入,红字可以看做是一个连接器,上面的第二个bean标签实现

    了声明接口对象userdao是指向Usertodo1这个实现类的,那么自然之前的userdao.adduser(newuser)实际上也就等

    于实例化一个Usertodo1对象,然后调用Usertodo1对象的adduser(newuser)方法。

    3.测试类通过对xml文件的操作来明确接口对象的指向

     1 public class Test1 {
     2     @Test
     3     public void add() {
     4         // Spring读取beans。xml文件
     5         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
     6         // 解析id为userservice的bean标签,内部实现UserDao userdao = new Usertodo1()
     7         Userservice service = (Userservice) ctx.getBean("userservice");
     8         User newuser = new User("桔子桑", 31);
     9         // 此时调用的useradd()方法,就是接口实现类Usertodo1的useradd()方法
    10         service.useradd(newuser);
    11     }
    12 }

    如此,就实现了通过xml文件来对Usertodo1的useradd(newuser)方法的调用。我为每个实现类的方法添加了标记,

    1 //Usertodo1类
    2 System.out.println("todo1 create the user");
    3 
    4 //Usertodo2类
    5 System.out.println("todo2 create the user");

    上面的bean文件配置,最后运行测试了类,控制台打印输出:

    1 todo1 create the user

    然后我们改一下上面的bean标签如下:

    1 <bean id="todo" class="com.eco.daoimp.Usertodo2"></bean>

    控制台打印输出:

    1 todo2 create the user

    这样我们只需通过更改bean文件就能实现对不同实现类方法的调用了,再也不用在代码中具体实例化这个实现类了,

    这就相当于把控制权交给了Spring,实现了控制反转。

  • 相关阅读:
    深入理解Linux修改hostname
    逆水行舟,不进则退
    TNS-12541: TNS:no listener TNS-12560 TNS-00511: No listener
    Linux Tomcat 6.0安装配置实践总结
    Database 'xxx' cannot be upgraded because it is read-only or has read-only file Make the database or files writeable, and rerun recovery.
    Tomcat启动找不到JRE_HOME的解决方法
    ORACLE触发器判断是否更新了某个字段
    MS SQL错误:SQL Server failed with error code 0xc0000000 to spawn a thread to process a new login or connection. Check the SQL Server error log and the Windows event logs for information about possible related problems
    MS SQL 错误:The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "test" was unable to begin a distributed transaction.
    ORA-01078: failure in processing system parameters & LRM-00109: could not open parameter file
  • 原文地址:https://www.cnblogs.com/eco-just/p/7842513.html
Copyright © 2011-2022 走看看