IoC: 控制反轉

:將傳統的由程序代碼直接操控對象的調用權交給容器.經過容器控制對象的裝配及生命週期管理.spring

(一下這兩段話摘自http://blog.csdn.net/m13666368773/article/details/7802126)編程

IOC中最基本的技術就是「反射(Reflection)」編程,目前.Net C#JavaPHP5等語言均支持,其中PHP5的技術書籍中,有時候也被翻譯成「映射」。有關反射的概念和用法,你們應該都很清楚,通俗來說就是根據給出的類名(字符串方式)來動態地生成對象。這種編程方式可讓對象在生成時才決定究竟是哪種對象。反射的應用是很普遍的,不少的成熟的框架,好比象Java中的hibernateSpring框架,.Net中 NHibernateSpring.NET框架都是把「反射」作爲最基本的技術手段。服務器

咱們能夠把IOC容器的工做模式看作是工廠模式的昇華,能夠把IOC容器看做是一個工廠,這個工廠裏要生產的對象都在配置文件中給出定義,而後利用編程語言的的反射編程,根據配置文件中給出的類名生成相應的對象。從實現來看,IOC是把之前在工廠方法裏寫死的對象生成代碼,改變爲由配置文件來定義,也就是把工廠和對象生成這二者獨立分隔開來,目的就是提升靈活性和可維護性。app

控制反轉的兩種實現方式:框架

1.依賴查找(DL)編程語言

2.依賴注入(DI): 程序在運行時,若須要調用另外一個對象協助,無需在代碼中建立而是依賴外部容器,由容器建立後傳遞給程序.ide

依賴注入是最優秀的解耦方式,依賴注入讓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的注入:this

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);
    }
}

運行截圖:

相關文章
相關標籤/搜索