沿着我們上一篇的學習筆記,我們繼續通過代碼學習IOC這一設計思想.
6.Hello類
第一步:首先創建一個類Hello
package cn.sxt.bean; public class Hello { private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello,"+name); } }
第二步:創建配置文件beans.xml
<?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就是java對象,由spring容器來創建和管理 --> <bean name="hello" class="cn.sxt.bean.Hello"> <property name="name" value="張三"></property> </bean> </beans>
第三步:編寫測試類Test
package cn.sxt.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.sxt.bean.Hello; public class Test { public static void main(String[] args) { //解析beans.xml文件生成管理相應的bean對象 ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); Hello hello=(Hello)context.getBean("hello"); hello.show(); } }
我們需要導入相關Jar包(在上一篇筆記Spring主要內容中顯示的那些核心jar包)
此時運行Test程序,會觸發異常:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
我們需要添加commons-logging.jar文件
步驟總結:
1)導入相關jar包
2)編寫spring配置文件(名稱可以自定義)
思考?
Hello對象是誰創建的?
我們在Hello類中添加一個構造函數,可以確定Hello對象確定被創建:
package cn.sxt.bean; public class Hello { public Hello() { System.out.println("hello 被創建"); } private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello,"+name); } }
運行Test測試類結果顯示:
hello 被創建
hello,張三
由此可以得知,Hello對象是由spring容器來創建的:bean工廠,可以包含多個bean,創建不同類的對象
<bean name="hello" class="cn.sxt.bean.Hello"> <property name="name" value="張三"></property> </bean>
Hello對象的屬性是怎樣設置的?
Hello對象的屬性是由spring容器來設置的;
這個過程就叫做控制反轉:
控制的內容:指的是誰來控制對象的創建;傳統的應用程序,對象的創建是由程序本身來控制,使用Spring以后是由spring來創建對象的。
反轉:有反轉就有正轉,正轉指程序來創建對象,反轉指程序本身不去創建對象,而變為被動的接收容器給我們創建的對象
總結:以前對象是由程序本身來創建,使用spring后,程序變為了被動接收spring創建好的對象;
控制反轉有一個別名--依賴注入(DI-dependency injection)
DI:比如在我們的Hello類中,我們的類Hello就依賴於name屬性,以來的這個name屬性是由spring容器來設置的,name值的設置過程就叫做依賴注入(通過setName方法進行的依賴注入)
Ioc--是一種編程思想,由主動編程變為別動接收;
Ioc的實現是通過Ioc容器(Bean工廠)來實現的。Ioc容器--BeanFactory
在第一篇學習筆記中的UserDao和UserDaoService的例子,我們在這里就可以使用spring配置文件的方式來管理對象的生命周期以及依賴對象的注入;
beanx.xml修改如下:
<?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就是java對象,由spring容器來創建和管理 --> <bean id="mysqlDao" class="cn.sxt.dao.impl.UserDaoMySqlImpl"></bean> <bean id="oracleDao" class="cn.sxt.dao.impl.UserDaoOracleImpl"></bean> <bean id="service" class="cn.sxt.service.impl.UserServiceImpl"> <!-- ref引用對象(對象是由spring來創建的) --> <property name="userDao" ref="mysqlDao"></property> </bean> <!-- property如何設置:name="setUserDao(去除set,並將剩余的UserDao首字母小寫)" --> </beans>
當我們需要替換具體的實現時,就可以直接在配置文件中進行修改,例如將ref="mysqlDao"修改為ref="oracleDao";
在測試類中我們就可以這樣來組織代碼:
package cn.sxt.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.sxt.service.UserService; public class Test { public static void main(String[] args) { ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); UserService us=(UserService)ac.getBean("service"); us.getUser(); } }
使用IOC來創建對象的方式:3種方式
1)通過無參的構造方法來創建;
User.java:
package cn.sxt.vo; public class User { public User(){ System.out.println("user的無參構造方法"); } private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); } }
beans.xml:
<?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 id="user" class="cn.sxt.vo.User"> <property name="name" value="張三"></property> </bean> </beans>
Test:
package cn.sxt.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.sxt.vo.User; public class Test { public static void main(String[] args) { ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); User user=(User)ac.getBean("user"); user.show(); } }
2)通過有參構造方法來創建;
User.java:
package cn.sxt.vo; public class User { private String name; public User(String name) { super(); this.name = name; } public void show(){ System.out.println("name="+name); } }
beans.xml配置(有三種情況):
第一種:根據參數的下標(index)來設置;
<?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 id="user" class="cn.sxt.vo.User"> <!-- index指的是構造方法參數下標,從0開始 --> <constructor-arg index="0" value="李四"></constructor-arg> </bean> </beans>
第二種:根據參數名稱(name)來設置;
<bean id="user" class="cn.sxt.vo.User"> <!-- name指的是屬性值 --> <constructor-arg name="name" value="王五"></constructor-arg> </bean>
第三種:根據參數類型(type)來設置;
<bean id="user" class="cn.sxt.vo.User"> <constructor-arg type="java.lang.String" value="徐六"></constructor-arg> </bean>
3)通過工廠方法來創建對象(有兩種);
第一種:靜態工廠來創建;
UserFactory.java:
package cn.sxt.factory; import cn.sxt.vo.User; public class UserFactory { public static User newInstance(String name){ return new User(name); } }
beans.xml配置:
<bean id="user" class="cn.sxt.factory.UserFactory" factory-method="newInstance"> <constructor-arg index="0" value="任七"></constructor-arg> </bean>
第二種:動態工廠來創建
UserDynamicFacory.java:
package cn.sxt.factory; import cn.sxt.vo.User; public class UserDynamicFactory { public User newInstance(String name){ return new User(name); } }
beans.xml:
<bean id="userFacotry" class="cn.sxt.factory.UserDynamicFactory"/> <bean id="user" factory-bean="userFacotry" factory-method="newInstance"> <constructor-arg index="0" value="王五"/> </bean>