Spring IoC控制反轉(zhuǎn)概念
csdn內(nèi)容同步桃序,id同名皂岔,csdn博客鏈接
Inversion of Control(IoC)控制反轉(zhuǎn):是一種通過描述(xml配置文件或注解)世蔗,并通過第三方去產(chǎn)生或獲取特定對象的方式铣猩。
實現(xiàn)控制反轉(zhuǎn)的是:IoC容器。
操作方法是:依賴注入弹灭。
控制反轉(zhuǎn)的結(jié)果是對象實例不再有調(diào)用者創(chuàng)建督暂,而是由Spring容器來創(chuàng)建,即控制權由調(diào)用者轉(zhuǎn)移到Spring容器穷吮。
Spring的依賴注入:Spring容器負責將被依賴的對象(需要的對象實例),賦值給調(diào)用者的成員變量饥努,相當于為調(diào)用者注入了它所依賴的實例捡鱼。
為什么要使用Spring IoC,作用是什么酷愧?
使用Spring IoC的作用是:消減程序間的耦合問題驾诈。
舉個栗子:比如在B類中需要一個A類的實例對象,在B類中若使用New關鍵字來創(chuàng)建A類實例溶浴,按如下所示:
package com.lipiao.demo;
public class A {
String name;
public void setName(String name) {
this.name = name;
}
}
package com.lipiao.demo;
public class B {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//修改前
A a=new A();
a.setName("A1");
System.out.println(a.name);
}
}
運行效果就是控制臺輸出A1:
實際開發(fā)中肯定不止2個類乍迄,隨著邏輯處理越來越多,這樣的處理方式會使不同的類之間耦合越來越嚴重士败,代碼的維護會比較困難闯两。
耦合:程序間的依賴關系
包括:①類之間的依賴 ②方法之間的依賴
弊端 獨立性很差
解耦:盡可能降低程序間的依賴關系(經(jīng)可能是因為有的耦合沒法避免)
實際開發(fā)中應該做到:編譯期間不依賴,運行時才依賴
解耦思路:
第一步:使用反射來創(chuàng)建對象谅将,而避免使用new關鍵字
第二步:通過讀取配置文件來獲取要創(chuàng)建的對象權限定類名
使用java的反射特性來修改上面的B類中的代碼漾狼,假設A類所在包路徑為:com.lipiao.demo.A
package com.lipiao.demo;
public class B {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//修改前
A a=new A();
a.setName("A1");
System.out.println(a.name);
//使用反射
Class<?> classA = Class.forName("com.lipiao.demo.A");
A a2=(A)classA.newInstance();
a2.setName("A2");
System.out.println(a2.name);
}
}
運行效果如下:
這樣New關鍵字就沒有啦,初步解耦就完成啦。
更多java反射特性的使用饥臂,本文不多撰寫啦逊躁,我找了一片博客:Java的高級特性 - 反射
但是以上代碼還沒有做到編譯期間不依賴,運行時才依賴隅熙。
進一步解耦就要使用Spring IoC控制反轉(zhuǎn)啦稽煤,通過依賴注入,讓IoC容器幫我們創(chuàng)建實例對象囚戚。
Spring IoC容器的基本使用
實現(xiàn)控制反轉(zhuǎn)的是:IoC容器酵熙。
Spring IoC容器的設計基于兩個接口:
①BeanFactory接口,使用絕對路徑
//3.使用Spring IoC容器 BeanFactory接口 使用絕對路徑
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource
("C:\\Users\\11092\\IdeaProjects\\javaEE\\src\\main\\resources\\META-INF\\applicationContext.xml"));
//通過容器創(chuàng)建A類實例,xml中id為A弯淘,getBean傳入A
A a3 = (A) beanFactory.getBean("A");
System.out.println(a3.name);
applicationContext.xml
<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 id="A" class="com.lipiao.demo.A">
<property name="name" value="A3"></property>
</bean>
</beans>
②ApplicationContext接口
1.使用ClassPathXmlApplicationContext創(chuàng)建ApplicationContext接口實例绿店,使用相對路徑(resources根目錄)
//4.使用Spring IoC容器 ApplicationContext接口
//有3種創(chuàng)建ApplicationContext接口的方式:
//4.1 ClassPathXmlApplicationContext 使用相對路徑(resources根目錄)
ApplicationContext applicationContext4_1 =
new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
A a4_1= (A) applicationContext4_1.getBean("A4_1");
System.out.println(a4_1.name);
applicationContext.xml
<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 id="A4_1" class="com.lipiao.demo.A">
<property name="name" value="A4_1"></property>
</bean>
</beans>
會有兩條紅色的提示信息,一條是刷新ClassPathXmlApplicationContext庐橙,一條是從xml配置文件中加載對應的bean文件
運行結(jié)果:控制臺輸出A4_1
2.使用FileSystemXmlApplicationContext創(chuàng)建ApplicationContext接口實例假勿,使用絕對路徑
//4.2 FileSystemXmlApplicationContext 使用絕對路徑
ApplicationContext applicationContext4_2= new FileSystemXmlApplicationContext(
"C:\\Users\\11092\\IdeaProjects\\javaEE\\src\\main\\resources\\META-INF\\applicationContext.xml");
A a4_2= (A) applicationContext4_2.getBean("A4_2");
System.out.println(a4_2.name);
applicationContext.xml
<bean id="A4_2" class="com.lipiao.demo.A">
<property name="name" value="A4_2"></property>
</bean>
會有兩條紅色的提示信息,一條是刷新ClassPathXmlApplicationContext态鳖,一條是從xml配置文件中加載對應的bean文件
運行結(jié)果:控制臺輸出A4_2
3.使用web服務器實例化ApplicationContext容器
一般使用基于org.springframework.web.context.ContextLoaderListener的實現(xiàn)方式转培,在web.xml文件中添加:
<context-parm>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-parm>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Spring IoC容器的依賴注入類型
①構(gòu)造方法注入
Spring框架可以采用java的反射機制,通過構(gòu)造方法完成依賴注入浆竭。
以下面這個C類為例:
package com.lipiao.demo;
//Spring IoC容器依賴注入 1.構(gòu)造方法注入
public class C {
String name;
public C(String name) {
this.name = name;
}
}
applicationContext.xml中
<bean id="C5_1" class="com.lipiao.demo.C">
<constructor-arg index="0" value="C_strName_constructor"/>
</bean>
index用于定義參數(shù)的位置浸须,value表示參數(shù)為常數(shù)惨寿,若為實例引用,將value替換為ref
運行效果:
會有兩條紅色的提示信息删窒,一條是刷新ClassPathXmlApplicationContext裂垦,一條是從xml配置文件中加載對應的bean文件
控制臺打印C_strName_constructor
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7d907bac: startup date [Wed Jul 17 21:12:40 CST 2019]; root of context hierarchy
七月 17, 2019 9:12:40 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [META-INF/applicationContext.xml]
C_strName_constructor
②使用屬性的setter方法注入(這是最主流的注入方式)
使用setter注入方法和構(gòu)造方法注入類似,剛剛在介紹Spring IoC容器的基本使用的案例都是使用屬性setter注入的肌索。
還是看個例子吧蕉拢,同樣是上面的C類,修改C類代碼诚亚,添加setter方法晕换,刪掉構(gòu)造方法:
package com.lipiao.demo;
//Spring IoC容器依賴注入
// 1.構(gòu)造方法注入
// 2.setter方法注入
public class C {
String name;
//構(gòu)造方法注入
// public C(String name) {
// this.name = name;
// }
//setter方法注入
public void setName(String name) {
this.name = name;
}
}
修改applicationContext.xml配置信息:
<bean id="C5_2" class="com.lipiao.demo.C">
<property name="name" value="C_strName_setter"/>
</bean>
運行效果:
會有兩條紅色的提示信息,一條是刷新ClassPathXmlApplicationContext站宗,一條是從xml配置文件中加載對應的bean文件
控制臺打印C_strName_setter
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@148080bb: startup date [Wed Jul 17 21:29:37 CST 2019]; root of context hierarchy
七月 17, 2019 9:29:37 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [META-INF/applicationContext.xml]
C_strName_setter