Spring-IOC使用實例詳解

 

實例12:引用外部屬性文件

舉例應用場景:對於數據庫連接池,只需要創建一個連接池即可,從中獲取連接對象。因此可以用IOC容器進行配置組件。

>數據庫連接池的配置文件(dbconfig.properties)

jdbc.username=root
jdbc.password=root
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/customersdb
jdbc.driverClass=com.mysql.jdbc.Driver

>在IOC容器中引入Context名稱空間

>通過 <context:property-placeholder/> 引入配置文件,其中classpath:固定用法表示引用類路徑下的配置文件

<context:property-placeholder location="classpath:dbconfig.properties"/>

>通過 ${ } 來動態獲取配置文件中的value值,並且需要注意的是,爲了防止username和Spring中自帶的username發生衝突,因此在配置

文件中應該在所有key值前加前綴,來避免衝突

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>

>最後在類文件中獲取IOC容器,並在方法中通過getBean方法獲取數據連接池對象,並調用其方法獲得連接對象

public class IOCTest {
	ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext02.xml");
	@Test
	public void test02() throws SQLException {
		//		DataSource bean = (DataSource)ioc.getBean("dataSource");
				
		//按照類型獲取組件,可以獲取到這個類型下的所有實現類子類等
		DataSource bean = ioc.getBean(DataSource.class);
		System.out.println(bean.getConnection());
	}

}

>需要注意的是,剛纔在編碼過程中,出現了java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector的錯誤,出現錯誤原因是沒有導入mchange-commons-java-0.2.11.jar。

 

實例13:基於XML的自動裝配

舉例應用場景:自動裝配應用於自定義類型屬性。假如一個類中的屬性爲自定義類,在Bean中配置時,可以通過<property name=" " ref=" IOC容器中的Bean"></property>進行手動裝配。

自動裝配:根據指定的裝配規則,不需要明確指定,就可以讓Spring自動將匹配的屬性值注入Bean中。

裝配模式:①<bean id=" " class=" " autowire="default"></bean>:不自動裝配

                  ②<bean id=" " class=" " autowire="byName"></bean>:根據屬性名稱,在IOC容器中尋找id和該屬性名稱相同的Bean,注入到Bean中

                  ③<bean id=" " class=" " autowire="byType"></bean>:根據屬性類型,在IOC容器中尋找類型相同的Bean,注入到Bean中

                  ④<bean id=" " class=" " autowire="constructor"></bean>:根據構造器中的參數,注入到Bean中。但是當一個Bean中存在多個構造器時就會很複雜,因此不建議使用。

大多時候會使用註解方式來實現自動裝配,在XML文檔中進行的自動裝配會顯得不方便,實際項目中更多使用註解的方式實現。

♥當一個類中的屬性時自定義類型的集合時,當自動裝配時,會將所有符合autowire條件的Bean都裝入該集合中。

 

實例14:SpEL(Spring Expression Language)測試

SpEL的語法符號爲:#{...}

>使用字面量進行賦值

<property name="count" value="#{5*12}"/>

>引用其他Bean的某個屬性值

<bean id="emp05" class="com.parent.bean.Employee">
	<property name="empId" value="1003"/>
	<property name="empName" value="Kate"/>
	<property name="age" value="21"/>
	<property name="deptName" value="#{dept.deptName}"/>
</bean>

>引用其他Bean,(不需要ref=""來引用其他Bean)

<bean id="emp04" class="com.parent.bean.Employee">
	<property name="empId" value="1003"/>
	<property name="empName" value="Kate"/>
	<property name="age" value="21"/>
	<property name="detp" value="#{dept}"/>
</bean>

>調用靜態方法:#{T(全類名).靜態方法名(參數)}

<bean id="employee" class="com.spel.bean.Employee">
	<!-- 在SpEL表達式中調用類的靜態方法 -->
	<property name="circle" value="#{T(java.lang.Math).PI*20}"/>
</bean>

>調用非靜態方法:#{對象.方法名}

<!-- 創建一個對象,在SpEL表達式中調用這個對象的方法 -->
<bean id="salaryGenerator" class="com.spel.bean.SalaryGenerator"/>

<bean id="employee" class="com.spel.bean.Employee">
	<!-- 通過對象方法的返回值爲屬性賦值 -->
	<property name="salayOfYear" value="#{salaryGenerator.getSalaryOfYear(5000)}"/>
</bean>

※實例15:通過註解分別創建Dao、Service、Controller

<!-- 實例15:通過註解分別創建Dao、Service、Controller(控制器:控制網站跳轉邏輯Servlet) -->
<!-- 通過給Bean上添加某些註解,可以快速的將Bean加入到IOC容器中
某個類上添加任何一個註解都能快速的將這個組件加入到IOC容器的管理中
Spring中有四個註解
@Controller:控制器:推薦給控制器層的組件添加該註解(Servlet包下)
@Service
@Rspository:給數據庫層(持久化層,Dao層)的組件添加該註解
@Componet:WebUtils:給不屬於以上基層的組件添加該註解

使用註解將組件快速加入容器中需要以下幾步
1>給要添加的組件上標四個註解中的任一個
2>告訴Spring自動掃描加了註解的組件:依賴context名稱空間
3>一定要導入AOP包,支持加註解模式的
 -->
 
 <!-- context:component-scan:自動組件掃描 -->
<context:component-scan base-package="com.cuco"></context:component-scan>
@Controller
public class BookServlet {

}
public class IOCTest {

	ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
	/*
	 * 使用註解加入到容器中的組件,和使用配置加入到容器中的組件行爲默認都是一樣的;
	 * 1.組件的id,默認就是組件的類名首字母小寫
	 * 2.組件的作用域,默認都是單例的
	 * >也可以新寫組件的新名字通過()
	 * >也可以將組件的作用域改爲多實例,@Scope(value="prototype")
	 * */
	@Test
	public void test() {
		Object bean = ioc.getBean("bookDao");
		Object bean1 = ioc.getBean("bookDao");
		System.out.println(bean == bean1);
		
	}

}

實例16:使用context:include-filter指定掃描包時要包含的類

實例17:使用context:include-filter指定掃描包時不包含的類

 
 <!-- context:component-scan:自動組件掃描 -->
<context:component-scan base-package="com.cuco"></context:component-scan>

<!-- 實例17:使用context:include-filter指定掃描包時不包含的類 -->
<context:component-scan base-package="com.cuco">
<!-- 掃描時可以排除一些不要的組件 
	type="annotation":指定排除規則:按照註解進行排除,標註了指定註解的組件不要
	expression="":註解的全類名
	
	type="assignable":指定排除某個具體的類,按照類排除
	expression="":類的全類名
-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="assignable" expression="com.cuco.service.BookService"/>
</context:component-scan>

<!-- use-default-filters設置爲false:不掃描所有組件 -->
<context:component-scan base-package="com.cuco" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

※實例18:使用@Autowired註解實現根據類型實現自動裝配

/*
 * @Autowired:Spring會自動的爲這個屬性賦值;
 * 			一定會去容器中找到這個屬性對應的組件

 * */
@Controller
public class BookServlet {
	
	//自動裝配,自動的爲這個屬性賦值,不需要new一個對象
	@Autowired
	private BookService bookService;
	
}

@Autowired註解

    [1]根據類型實現自動裝配。

    [2]構造器、普通字段(即使是非public)、一切具有參數的方法都可以應用@Autowired註解

    [3]默認情況下,所有使用@Autowired註解的屬性都需要被設置。當Spring找不到匹配的bean裝配屬性時,會拋出異常。

    [4]若某一屬性允許不被設置,可以設置@Autowired註解的required屬性爲 false

    [5]默認情況下,當IOC容器裏存在多個類型兼容的bean時,Spring會嘗試匹配bean的id值是否與變量名相同,如果相同則進行裝配。如果bean的id值不相同,通過類型的自動裝配將無法工作。此時可以在@Qualifier註解裏提供bean的名稱。Spring甚至允許在方法的形參上標註@Qualifiter註解以指定注入bean的名稱。

    [6]@Autowired註解也可以應用在數組類型的屬性上,此時Spring將會把所有匹配的bean進行自動裝配。

    [7]@Autowired註解也可以應用在集合屬性上,此時Spring讀取該集合的類型信息,然後自動裝配所有與之兼容的bean。

    [8]@Autowired註解用在java.util.Map上時,若該Map的鍵值爲String,那麼 Spring將自動裝配與值類型兼容的bean作爲值,並以bean的id值作爲鍵。

※實例19:如果資源類型的bean不止一個,默認根據@Autowired註解標記的成員變量名作爲id查找bean,進行裝配

※實例20:如果根據成員變量名作爲id還是找不到bean, 可以使用@Qualifier註解明確指定目標bean的id

public class BookServlet {
	
	//自動裝配,自動的爲這個屬性賦值,不需要new一個對象
	//@Qualifier:指定一個名字作爲該組件的id,讓Spring不要使用變量名作爲id
	@Qualifier("bookService")
	@Autowired
	private BookService bookServiceExt2;

}

※實例21:@Autowired註解的required屬性指定某個屬性允許不被設置:@Autowired(required="false")

總結@Autowired流程:

1>按照所註解的類型去Spring容器中尋找對應的組件:BookService bookService = ioc.getBean(BookService.class)

      (1)如果找到一個對應的組件,則賦值給變量bookService;

    (2)如果沒找到,則拋出異常

      (3)如果找到多個(例如會將bookService所有的子類找出)

           ①根據變量名作爲id繼續匹配:

                             如果匹配上,則裝配;匹配不上,則報錯。

                                                                 如果想要根據變量名作爲id繼續匹配,可以使用@Qualifier("")指定一個新id

@Autowired和@Resource的區別

@Autowired:是Spring自己的註解,相比較來說功能強大一些,但如果離開Spring框架就不能使用

@Resource:是Java中的註解,擴展性強,如果換一個不是Spring的容器框架(例如EJB),該註解依然可以使用

 

使用Spring的單元測試

好處:不需要自己通過getBean方法獲取組件,直接通過註解就可以讓Spring自動裝配

/*
 * 使用Spring的單元測試
 * 1.導包:導入Spring單元測試包 spring-test-4.0.0.RELEASE.jar
 * 2.@ContextConfiguration(LOCATION="")使用它來指定Spring的配置文件的位置
 * 3.@RunWith指定用那種驅動進行單元測試,默認是junit
 * 	@RunWith(org.springframework.test.context.junit4.SpringJUnit4ClassRunner.class)
 * 	使用Spring的單元測試模塊來執行標了@Test註解的測試方法
 * 	以前@Test註解只是由junit執行,現在Spring中的單元測試模塊會根據指定的配置文件自動幫你創建ioc容器
 * */
@ContextConfiguration(locations="classpath:applicationContext.xml")
@RunWith(org.springframework.test.context.junit4.SpringJUnit4ClassRunner.class)
public class IOCTest {

	//ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
	ApplicationContext ioc = null;
	@Autowired
	BookServlet bookServlet;
	
	
	@Test
	public void test() {
		System.out.println(bookServlet);
		
	}

}

實例23:測試泛型依賴注入

Spring 4.x中可以爲子類注入子類對應的泛型類型的成員變量的引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章