IoC: 控制反转

:将传统的由程序代码直接操控对象的调用权交给容器.通过容器控制对象的装配及生命周期管理.

(一下这两段话摘自http://blog.csdn.net/m13666368773/article/details/7802126)

IOC中最基本的技术就是“反射(Reflection)”编程,目前.Net C#JavaPHP5等语言均支持,其中PHP5的技术书籍中,有时候也被翻译成“映射”。有关反射的概念和用法,大家应该都很清楚,通俗来讲就是根据给出的类名(字符串方式)来动态地生成对象。这种编程方式可以让对象在生成时才决定到底是哪一种对象。反射的应用是很广泛的,很多的成熟的框架,比如象Java中的hibernateSpring框架,.Net中 NHibernateSpring.NET框架都是把“反射”做为最基本的技术手段。

我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

控制反转的两种实现方式:

1.依赖查找(DL)

2.依赖注入(DI): 程序在运行时,若需要调用另一个对象协助,无需在代码中创建而是依赖外部容器,由容器创建后传递给程序.

依赖注入是最优秀的解耦方式,依赖注入让Springbean 之间以配置文件方式组织在一起而不是硬编码的方式.

 

控制反转Demo1:
/*dao层接口*/
public interface IStudentDao {
    public void selectStudent(int cid);
}
/*dao层实现类*/
public class StudentDaoImpl implements IStudentDao {
    public StudentDaoImpl() {
        super();
        System.out.println("构造函数执行!");
    }
    @Override
    public void selectStudent(int cid) {
        System.out.println("查找学生"+cid);
    }
/*Sping配置文件中注册实现类bean*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- bean definitions here -->
        <bean id="sdImpl" class="com.xiehe.dao.StudentDaoImpl"/>
</beans>
/*测试类中*/
public class MyTest {
    @Test
    public void test01(){
        //1.获取容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationSpring.xml");
        //2.从容器中获取对象
        IStudentDao sdImpl = (IStudentDao) context.getBean("sdImpl");
        sdImpl.selectStudent(1);
    }
 :结果截图

 本例中可以明显看出,在测试类中获取StudentDaoImpl 是通过容器(调用了构造)而不是依赖于StudentDaoImpl 
 

ApplicationContext 用于加载Spring 配置文件,在程序中充当容器.其实现类有两

a)基于xml的注入:

Bean的初始化由容器完成称为注入.根据注入方式不同分为 设值注入 和 构造注入

1)设值注入 通过setter 方法传入被调用者的实例中

2)构造注入 调用构造函数完成注入

 

/*实体类:schol*/
public class School {
    private String name;
    private String addr;
    public School(String name, String addr) {
        super();
        this.name = name;
        this.addr = addr;
    }
    public School() {
        super();
    }
Getter/setter
}
/*实体类:Student*/
public class Student {
    private String name;
    private int age;
    private School mySchool;
    public Student() {
        super();
    }
    public Student(String name, int age, School mySchool) {
        super();
        this.name = name;
        this.age = age;
        this.mySchool = mySchool;
    }
Getter/setter
}
/*spring配置文件*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- bean definitions here -->
    <!-- 设值注入 -->
        <bean id="mySchool" class="com.xiehe.dao.School">
            <property name="name" value="北京大学"></property>
            <property name="addr" value="海淀区"></property>
        </bean>
        <!-- 设值注入 -->
        <bean id="sdImpl" class="com.xiehe.dao.Student" >
            <property name="name" value="张赛"/>
            <property name="age" value="58"/>
            <!-- 域类型注入方式1:-- >
            <!-- <property name="mySchool" ref="mySchool"/> -->
            <!-- 域类型注入方式2:-- >
            <property name="mySchool">
                <ref bean="mySchool"/>
            </property>
        </bean>
        <!-- 构造注入 -->
        <bean id="sdImpl2" class="com.xiehe.dao.Student">
            <constructor-arg name="name" value="张赛"/>
            <constructor-arg name="age" value="58"/>
            <constructor-arg name="mySchool" ref="mySchool"/>
        </bean>    
</beans>
/*测试类*/
public class MyTest {
    @Test
    public void test01(){
        //1.获取容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationSpring.xml");
        //2.从容器中获取对象(设值注入)
        Student dao = (Student) context.getBean("sdImpl");
        System.out.println(dao);    
    }
    @Test
    public void test02(){
        //1.获取容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationSpring.xml");
        //2.从容器中获取对象(构造注入)
        Student dao = (Student) context.getBean("sdImpl2");
        System.out.println(dao);    
    }
}

 

Test01 结果截图:
Test02 结果截图:

b)基于注解的注入:

     在Spring 配置文件中添加组件扫描器:

<context:component-scan base-package="com.xiehe.dao"/>

 在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的Java文件,如果扫描到有@Component (普通bean)@Controller(控制器)@Service(服务器)等这些注解的类,则把这些类注册为bean.

 

/*注解式注入 */
@Component("school1")
public class School {
    @Value("清华大学")
    private String name;
    @Value("海淀区")
    private String addr;
}
/*注解式注入*/
@Component(value="stu1")
public class Student {
    @Value("张嘴")
    private String name;
    @Value("44")
    private int age;
    //默认 byType
    @Autowired
    private School mySchool;
}
/*spring 配置文件*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- bean definitions here -->
    <!-- 配置组件扫描器 -->
    <context:component-scan base-package="com.xiehe.dao"/>    
</beans>    
/*测试类*/
public class MyTest {
    @Test
    public void test01(){
        //1.获取容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/xiehe/dao/applicationSpring.xml");
        //2.从容器中获取对象
        Student dao = (Student) context.getBean("stu1");
        System.out.println(dao);
    }
}

运行截图:

 

posted @ 2016-11-23 13:45  鹤少  阅读(185)  评论(0编辑  收藏  举报