1. 程式人生 > >Spring框架——關於IOC容器和註解的36個小實驗

Spring框架——關於IOC容器和註解的36個小實驗

web beans count 註入 定義 目標 初始化 getc pan

實驗1:通過IOC容器創建對象,並為屬性賦值★

<bean id="page"  class="com.neuedu.Bean.Page">

<property name="fontSize" value="大寫"></property>

<property name="fontNum" value="12"></property>

</bean>

 

ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");

Page bean2 = (Page)iocContainer.getBean("page");

實驗2:根據bean的類型從IOC容器中獲取bean的實例★

<bean id="page"  class="com.neuedu.Bean.Page">

<property name="fontSize" value="大寫"></property>

<property name="fontNum" value="12"></property>

</bean>

 

ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");

Page bean2 = iocContainer.getBean(Page.class);

  

實驗3:通過構造器為bean的屬性賦值

<bean id="Book" class="com.neuedu.Bean.Book">

<!-- 以下為給帶參構造器傳送參數 -->

<constructor-arg value="123" ></constructor-arg>

<constructor-arg value="456" ></constructor-arg>

<constructor-arg value="789" ></constructor-arg>

</bean>

  

實驗4:通過index屬性指定參數的位置

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="num" value="123"></property>

<constructor-arg value="123" index="0"></constructor-arg>

<constructor-arg value="123" index="1"></constructor-arg>

<constructor-arg value="123" index="2"></constructor-arg>

</bean>

  

實驗5:通過類型不同區分重載的構造器

<bean id="page"  class="com.neuedu.Bean.Page">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

  

實驗6:通過p名稱空間為bean賦值

<bean id="Book2"  parent="Book"

p:num="254"

 />

  

實驗14:給bean的級聯屬性賦值

<bean id="page"  class="com.neuedu.Bean.Page">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="page" ref="page"></property>

</bean>

  

實驗21:測試bean的作用域,分別創建單實例和多實例的bean

<bean id="page" scope="prototype" class="com.neuedu.Bean.Page">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

  

Scope屬性:

Prototype:每次從容器中調用Bean時,都返回一個新的實例,即每次調用getBean()時,相當於執行new XxxBean()的操作

Request:每次Http請求都會創建一個新的Bean, 僅適用於WebApplication環境

Session:每次創建一個session,創建對象,同一個Http Session共享一個Bean,不同的HttpSession使用不同的Bean。僅適用於WebApplication環境

Singleton:Spring容器中僅存在一個Bean實例,Bean以單例的方式存在

實驗22:創建帶有生命周期方法的bean

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" init-method="int" destroy-method="destroy">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

  

實驗20bean之間的依賴 depends-on="order"被依賴的對象會先創建

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" depends-on="font">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

<bean id="font" class="com.neuedu.Bean.Font"></bean>

  

實驗18:通過繼承實現bean配置信息的重用

<bean id="Book"  class="com.neuedu.Bean.Book" 

p:name="四大名著"

p:num="258"

 />

 

 <bean id="Book2"  parent="Book"

p:num="254"

 />

  

實驗19:通過abstract屬性創建一個模板bean

<bean id="Book"  abstract="true" class="com.neuedu.Bean.Book" 

p:name="四大名著"

p:num="258"

 />

 

 <bean id="Book2"  parent="Book"

p:num="254"

 />

  

實驗7:測試使用null

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" >

<property name="fontSize">

<null/>

</property>

</bean>

  

null只有包裝類和引用類型可以用

實驗8:引用其他bean

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="page" ref="page"></property>

</bean>

  

實驗9:引用內部bean

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="page" >

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" >

<property name="fontSize" value="123"></property>

</bean>

</property>

</bean>

  

實驗10:使用List類型的集合屬性

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petList" ref="petList" />

</bean>

 

<util:list id="petList" list-class="java.util.ArrayList" value-type="java.lang.String">

<value>DOG</value>

<value>CAT</value>

<value>BIRD</value>

</util:list>

  

實驗11:使用Map類型的集合屬性

<!-- 第一種寫法 ,通過ref引用,此時需要在 uitl-map中聲明id 推薦這種寫法

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petMap" ref="petMap" />

</bean>

<util:map id="petMap" map-class="java.util.HashMap">

<entry key="101" value="dog" />

<entry key="103" value="wolf" />

<entry key="105" value="bird" />

</util:map> --> 

 

<!-- 第二種寫法,嵌入內部 -->

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petMap">

<util:map map-class="java.util.HashMap">

<!-- 可以通過map-class顯示指定Map的實現類 -->

<entry key="101" value="dog" />

<entry key="103" value="wolf" />

<entry key="105" value="bird" />

</util:map>

</property>

</bean>

  

實驗12:使用prop子元素為Properties類型的屬性賦值

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petProperties" ref="petProperties" />

</bean>

 

<util:properties id="petProperties">

<prop key="151">PIG</prop>

<prop key="153">PINGUIN</prop>

</util:properties>

  

實驗15:配置通過靜態工廠方法創建的bean[通過靜態方法提供實例對象,工廠類本身不需要實例化!]

<bean id="staticFactory" class="com.neuedu.spring.bean.StaticFactory" factory-method="getBook">

<constructor-arg value="book01"></constructor-arg>

</bean>

  

實驗16:配置通過實例工廠方法創建的bean[通過實例方法提供實例對象,工廠類本身需要先創建對象!]

<bean id="instanceFactory" class="com.neuedu.spring.bean.InstanceFactory"></bean>

<bean id="bookFromInstanceFactory" factory-bean="instanceFactory" factory-method="getBook">

<constructor-arg value="book02"></constructor-arg>

</bean>

  

實驗17:配置FactoryBean

public class MyFactoryBean implements FactoryBean<Book> {

 

@Override

public Book getObject() throws Exception {

return new Book(22, "無字天書", "好啊", 22.5);

}

 

@Override

public Class<?> getObjectType() {

return Book.class;

}

 

@Override

public boolean isSingleton() {

return false;

}

}

  

實驗22[補充]:測試bean的後置處理器

①在bean的初始化方法調用前後執行操作的專門的對象

②自定義後置處理器實現該接口:org.springframework.beans.factory.config.BeanPostProcessor

③在springmvc中配置一下該bean對象.

<bean class="com.neuedu.spring.bean.Book" init-method="init"></bean>

<bean id="myBeanPostProcessor" class="com.neuedu.spring.bean.MyBeanPostProcessor"></bean>

  

數據庫連接池:

6) 數據庫連接池

> 數據庫連接池就是存放數據庫連接(Connection)的集合

> 我們獲取一個數據庫連接是一個相對很麻煩的過程,

如果我們獲取一個數據庫連接,使用一次以後就給它關閉了

下一次再去使用的時候就要重新創建一個新的數據庫連接。

> 所以我們提出了一個數據庫連接池的概念,數據庫連接池放的都是數據庫連接(Connection

我們在去使用數據庫連接時候,不用再去重新創建數據庫連接,而是直接從池中獲取,

使用完的數據庫連接,也不是直接銷毀,而是要放回到連接池。

>

數據庫連接池的常見的屬性:

初始連接數量:數據連接池創建以後,保存數據庫連接的數量[50]

最小空閑連接數:數據庫連接池最少得未使用的數據庫連接的數量[10]

最大空閑連接數:數據庫連接池最大閑置連接數,當閑置連接數滿了以後,將不會有其他連接進入池

每次增加連接數:當數據庫連接都被占用以後,一次性增加的數據庫連接的個數[20]

最大連接數:數據庫連接池的最大容量,當最大連接數飽和了,則不再創建新的數據庫連接[100]

最大等待時間:當數據庫連接池飽和以後,等待獲取數據庫連接的時間

> 常見的數據庫連接池

- 所有的數據庫連接池都需要實現DataSource,當使用數據庫連接池是,我們便不再需要使用DriverManger獲取數據庫連接

而是使用DataSource

- Connection getConnection()

- 從數據庫連接池中獲取數據庫連接對象

1.DBCP

- DBCPApache出品的一款數據庫連接

- DBCP依賴於commons-pool

- 使用DBCP需要導入兩個jar包:

commons-dbcp-1.4.jar

commons-pool-1.5.5.jar

- 當我們通過數據庫連接池獲取數據庫連接以後,我們所獲取到數據庫連接已經不是我們熟悉的那個Connection

數據庫連接池對Connection對象進行了包裝,它修改Connectionclose()方法,

再去調用close()數據庫連接將不會真的關閉,而是要放回到數據庫連接池中,供其他線程使用。

- 核心類:

BasicDataSourceFactory

2.C3P0(重點)

- C3P0使用的是XML作為配置文件

- 使用c3p0需要導入一個jar包:

c3p0-0.9.1.2.jar

- 導入c3p0的配置文件:

1.配置文件的名字:c3p0-cofig.xml

2.配置文件要求放到類路徑下(src

- 核心類:

ComboPooledDataSource

- 註意:

DataSource就相當於池子,我們的數據庫連接都是從DataSource中獲取的,

如果程序中有多個DataSource的實例,那麽我們說你還不如不用數據庫連接池。

所以我們的DataSource在項目中應該只有一個實例。

實驗23:引用外部屬性文件★

jdbc.properties文件:

jdbc.user=root

jdbc.passowrd=123456

jdbc.url=jdbc:mysql://localhost:3306/test

jdbc.driver=com.mysql.jdbc.Driver

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

1.在目標屬性上加@Value註解

@Value("${jdbc.user}")

private String username;

2.

<!-- 根據外部屬性文件中的信息配置數據源 -->

<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="user" value="${jdbc.user}"></property>

<property name="password" value="${jdbc.passowrd}"></property>

<property name="jdbcUrl" value="${jdbc.url}"></property>

<property name="driverClass" value="${jdbc.driver}"></property>

</bean>

 

 

ComboPooledDataSource bean = ioc.getBean(ComboPooledDataSource.class);

Connection connection = bean.getConnection();

System.out.println(connection);

Statement st = connection.createStatement();

ResultSet rs = st.executeQuery("select * from stu");

while(rs.next()){

String string = rs.getString("name");

String string2 = rs.getString("school");

System.out.println(string+"==="+string2);

}

  

實驗24:基於XML的屬性裝配

①手動裝配

<!-- 屬性的裝配:手動裝配 -->

<bean id="userService" class="com.neuedu.spring.bean.UserService"></bean>

<bean  id="userAction" class="com.neuedu.spring.bean.UserAction">

<property name="userService" ref="userService"></property>

</bean>

  

②自動裝配

<!-- 1.按類型裝配:byType -->

<!-- 首先檢測當前bean中需要裝配的屬性的類型 -->

<!-- 然後在IOC容器中查找匹配這個類型的bean -->

<!-- 如果類型匹配的bean是唯一的,那麽就將這個匹配的bean註入到userAction中 -->

 

<bean id="userService" class="com.neuedu.spring.bean.UserService"></bean>

<bean  id="userAction" autowire="byType" class="com.neuedu.spring.bean.UserAction"></bean>

 

<!-- 2.按bean的id值裝配:byName -->

<!-- 首先檢測當前bean中需要裝配的屬性的屬性名,屬性名是將setXxx()方法去掉set,首字母小寫得到的 -->

<!-- 然後根據屬性名作為id的值,在IOC容器中查找對應的bean -->

<!-- 如果能夠找到,則將找到bean註入進去 -->

  

6SpEL簡介【見WORLD文檔---了解】

Spring Expression LanguageSpring表達式語言,簡稱SpEL。支持運行時查詢並可以操作對象圖。

JSP頁面上的EL表達式、Struts2中用到的OGNL表達式一樣,SpEL根據JavaBean風格的getXxx()setXxx()方法定義的屬性訪問對象圖,完全符合我們熟悉的操作習慣。

6.1 基本語法

SpEL使用#{}作為定界符,所有在大框號中的字符都將被認為是SpEL表達式。

6.2 使用字面量

●整數:<property name="count" value="#{5}"/>

●小數:<property name="frequency" value="#{89.7}"/>

●科學計數法:<property name="capacity" value="#{1e4}"/>

String類型的字面量可以使用單引號或者雙引號作為字符串的定界符號

<property name=namevalue="#{‘Chuck‘}"/>

<property name=‘name‘ value=‘#{"Chuck"}‘/>

Boolean<property name="enabled" value="#{false}"/>

實驗25[SpEL測試I]SpEL中使用字面量

實驗26[SpEL測試II]SpEL中引用其他bean

實驗27[SpEL測試III]SpEL中引用其他bean的某個屬性值

實驗28[SpEL測試IV]SpEL中調用非靜態方法

實驗29[SpEL測試V]SpEL中調用靜態方法

實驗30[SpEL測試VI]SpEL中使用運算符

8.使用註解配置bean

①聲明bean的註解

@Component 將當前類聲明為IOC容器中的一個普通的組件

@Controller 將當前類聲明為IOC容器中的一個控制器組件

@Service 將當前類聲明為IOC容器中的業務邏輯層組件

@Repository 將當前類聲明為IOC容器中的一個持久化層組件

@ControllerAdvice

Spring根據上述註解其實並不能分辨當前類是否真的是一個控制器或Dao,即使標記的類和註解不對應也沒有語法錯誤。

但在實際工作中,肯定要將專門的註解標記在對應的類上面。

②使用基於註解的bean的配置,需要額外導入一個jar包:spring-aop-4.0.0.RELEASE.jar

③需要設置自動掃描的包

< context:component-scan base-package ="com.neuedu.ioc.bean"/>

④使用註解後,默認按照類名首字母小寫作為id的值,也可以使用value屬性指定idvalue屬性名也可以省略註解

註解 id值

@Component

public class CommonComponent {

}

commonComponent

@Controller(value="neueduBookAction" )

public class BookAction {

}

neueduBookAction

@Service("happyService" )

public class BookService {

}

happyService

實驗31:通過註解分別創建DaoServiceController

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

實驗33:使用context:exclude-filter指定掃描包時不包含的類

< context:component-scan base-package ="com.neuedu.ioc.bean"/>

[1]base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包及其子包中的所有類。

[2]當需要掃描多個包時可以使用逗號分隔,

[3]如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類,示例:

<context:component-scan base-package="com.neuedu.component" resource-pattern="autowire/*.class"/>

[4]包含與排除

<context:include-filter>子節點表示要包含的目標類

註意:通常需要與use-default-filters屬性配合使用才能夠達到“僅包含某些組件”這樣的效果。

即:通過將use-default-filters屬性設置為false,禁用默認過濾器,然後掃描的就只是include-filter中的規則

指定的組件了。

<context:exclude-filter>子節點表示要排除在外的目標類

component-scan下可以擁有若幹個include-filtejrexclude-filter子節

⑤使用註解進行自動裝配:@Autowired註解[好處就是:連getset方法都不用寫!]

[1]首先檢測標記了@Autowired註解的屬性的類型

[2]根據類型進行裝配

[3]如果指定類型的bean不止一個,那麽根據需要被裝配的屬性的屬性名做id的值,查找bean

[4]如果根據id值還是沒有找到bean,可以使用@Qualifier註解手動指定要裝配的beanid.

實驗34:使用@Autowired註解實現根據類型實現自動裝配★

實驗34[補充1]:如果資源類型的bean不止一個,默認根據@Autowired註解標記的成員變量名作為id查找bean,進行裝配★

實驗34[補充2]:如果根據成員變量名作為id還是找不到bean,可以使用@Qualifier註解明確指定目標beanid

實驗36Autowired註解的required屬性指定某個屬性允許不被設置.

實驗37:在類上使用註解@Scope可以指定對象是單實例還是多實例的!

Spring框架——關於IOC容器和註解的36個小實驗