第一種: 使用無參構造函數(重點第一種,二三種已經沒太多人用了)
hi是一個簡單的bean , 只有println();
<bean id="binbin" class="test_one.hi"></bean>
id 是唯一標識, class是類路徑(src/main/java是默認路徑,不可更改,所以必須在該目錄下添加包,並且為了能找到該類,該類需要在頭上加package,很顯然兩者是對應的)
scope: 指定對象作用范圍 singleton : 默認值,單例模式(只要被實例化,該實例就會一直存活,除非容器銷毀或退出,並且IoC容器只存在一個實例,所有對該對象的引用將共享這個實例) prototype: 多例模式(每次請求都將創建一個新的實例,當實例長時間不用會被java的垃圾回收機制回收)
request, session, global session 這三種只適用於web應用程序,通常是與XmlWebApplicationContext共同使用
單例模式:
多例模式:
如果創建一個新的實例classpathxmlapplicationcontext, 他們之間的地址是不一樣的,由於ApplicationContext是繼承BeanFactory,所以我們可以說
在同一個容器內,單例模式下的實例為同一實例,在同一容器內訪問該實例為同一實例,引用對象共享實例
從上面的singleton模式我們就能明白,為什么一個實例可以一直存在並且對該對象的引用都共享這個實例. 如果這個實例要不一樣的屬性呢?
bean就是可復用的類, 因為有的類每次我們實例化就只要用里面的函數, 不需要將實例當作數據一樣對待..而bean的出現就解決了繁瑣地創建實例以及浪費內存資源
那為什么是無參構造函數呢? 因為可復用類不能用有參構造函數
下面是如何從配置文件中獲得實例化bean
可以看出,我們通過bean.xml文件,通過getBean(唯一標識id)得到我們想要的對象,而不用我們主動去創建對象,這就是典型的工廠模式。 getBean是BeanFactory接口的方法,返回得對應id的實例。
第二種 :使用靜態工廠創建
bean.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="binbin" class="test_one.hi"></bean> <!--使用靜態工廠實例化--> <bean id="static" class="test_one.static_test" factory-method="sayStatic"></bean> </beans>
id 唯一標識; class 類路徑; factory-method 工廠方法名
static_test類
如何通過靜態工廠得到實例
第一種是直接從配置文件bean.xml得到實例,而第二種是從配置文件bean.xml尋找對應的靜態方法,再從靜態方法返回實例。
那么靜態工廠是單例模式嗎? 就是每次調用的時候不會創建新的實例,會共享實例。
在spring中默認是單例模式, 不在spring是多例
下圖為不在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 id="binbin" class="test_one.hi" scope="prototype"></bean> <!--使用靜態工廠實例化--> <bean id="static" class="test_one.static_test" factory-method="sayStatic"></bean> <!--使用實例工廠實例化--> <bean id="instance" class="test_one.instance"></bean> <bean id="createInstance" factory-bean="instance" factory-method="createHi"></bean> </beans>
instance.java
得到實例化
第三種有點復雜
靜態工廠模式和實例模式都會多實例化一個對象,也就是靜態方法或者方法所在的類
以上三種實例化bean的方法, 在程序開始運行后就已經實例化了, 如果在bean中加入構造函數就會發現哪怕沒有獲取實例化也執行了構造函數, 這就說明開始就已經實例化了
參考:
非實例化bean, 抽象bean:
abstract屬性為true,表示該bean為抽象bean,不會被實例化,但是其屬性可以注入到其它bean中
抽象bean的一個好處就是做模板 , 如果兩個類有相同的屬性,那么可以注入抽象bean來解決通過兩次重復操作來注入該屬性
abstract="true"
//兩個有相同屬性的類(不用聲明父類) public class FooDao { private DataSource dataSource; private SomeHelper someHelper; private FooHelper fooHelper; //setters } public class BarDao { private DataSource dataSource; private SomeHelper someHelper; private BarHelper barHelper; //setters }
//xml定義抽象bean(並不會實例化這個bean) <bean id="dao" abstract="true"> <!--實際根本沒有這個類--> <property name="dataSource" ref="dataSource"/> <property name="someHelper" ref="someHelper"/> </bean> <!--指定parent為dao,則只需要再注入自己特別的屬性即可--> <bean id="fooDao" class="FooDao" parent="dao"> <property name="fooHelper" ref="fooHelper" /> </bean> <bean id="barDao" class="BarDao" parent="dao"> <property name="barHelper" ref="barHelper" /> </bean>
抽象bean不是指抽象類,其實根本就沒有這個類
抽象bean的屬性在子bean一定是擁有的, 如果沒有就會報錯
如果子bean注入了數據, 那么取得是子bean的值
如果有多個bean有相同的屬性並且值也相同(個別bean不同) , 那么可以用抽象bean來注入相同的屬性, 並且還不影響個別子bean的值不同
所以抽象bean作為模板特別好