:將傳統的由程序代碼直接操控對象的調用權交給容器.經過容器控制對象的裝配及生命週期管理.spring
(一下這兩段話摘自http://blog.csdn.net/m13666368773/article/details/7802126)編程
IOC中最基本的技術就是「反射(Reflection)」編程,目前.Net C#、Java和PHP5等語言均支持,其中PHP5的技術書籍中,有時候也被翻譯成「映射」。有關反射的概念和用法,你們應該都很清楚,通俗來說就是根據給出的類名(字符串方式)來動態地生成對象。這種編程方式可讓對象在生成時才決定究竟是哪種對象。反射的應用是很普遍的,不少的成熟的框架,好比象Java中的hibernate、Spring框架,.Net中 NHibernate、Spring.NET框架都是把「反射」作爲最基本的技術手段。服務器
咱們能夠把IOC容器的工做模式看作是工廠模式的昇華,能夠把IOC容器看做是一個工廠,這個工廠裏要生產的對象都在配置文件中給出定義,而後利用編程語言的的反射編程,根據配置文件中給出的類名生成相應的對象。從實現來看,IOC是把之前在工廠方法裏寫死的對象生成代碼,改變爲由配置文件來定義,也就是把工廠和對象生成這二者獨立分隔開來,目的就是提升靈活性和可維護性。app
控制反轉的兩種實現方式:框架
1.依賴查找(DL)編程語言
2.依賴注入(DI): 程序在運行時,若須要調用另外一個對象協助,無需在代碼中建立而是依賴外部容器,由容器建立後傳遞給程序.ide
依賴注入是最優秀的解耦方式,依賴注入讓Spring的bean 之間以配置文件方式組織在一塊兒而不是硬編碼的方式.函數
控制反轉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); } }
運行截圖: