Spring框架03-IOC應用

Spring IOC應用

Spring IOC基礎

image.png

BeanFactory與ApplicationContext區別

  • BeanFactory是Spring框架中IoC容器的頂層接⼝,它只是⽤來定義⼀些基礎功能,定義⼀些基礎規範
  • ApplicationContext是它的⼀個⼦接⼝,因此ApplicationContext是具有BeanFactory提供的所有功能的

一般,咱們稱BeanFactory爲SpringIOC的基礎容器ApplicationContext是容器的⾼級接⼝,⽐BeanFactory要擁有更多的功能,好比說國際化支持和資源訪問(xml,java配置類)等等
image.pngjava

啓動IOC容器方式

  • Java環境下啓動IOC容器spring

    • ClassPathXmlApplicationContext:從類的根路徑下加載配置文件(推薦使用)
    • FileSystemXmlApplicationContext:從磁盤路徑上加載文件
    • AnnotationConfigApplicationContext:純註解模式下加載配置類

Bean的做用範圍及⽣命週期

做⽤範圍的改變

在spring框架管理Bean對象的建立時,Bean對象默認都是單例的,可是它⽀持配置的⽅式改變做⽤範圍。做⽤範圍官⽅提供的說明以下圖:
image.png數據庫

在上圖中提供的這些選項中,咱們實際開發中⽤到最多的做⽤範圍就是singleton(單例模式)和prototype(原型模式,也叫多例模式)。配置⽅式參考下⾯的代碼:服務器

<!--配置service對象-->
<bean id="transferService" class="com.lagou.service.impl.TransferServiceImpl" scope="singleton">
</bean>

不一樣做⽤範圍的⽣命週期

單例模式 singleton
  • 對象出⽣:當建立容器時,對象就被建立了
  • 對象活着:只要容器在,對象⼀直活着
  • 對象死亡:當銷燬容器時,對象就被銷燬了
⼀句話總結:單例模式的bean對象⽣命週期與容器相同
多例模式 prototype
  • 對象出⽣:當使⽤對象時,建立新的對象實例
  • 對象活着:只要對象在使⽤中,就⼀直活着
  • 對象死亡:當對象⻓時間不⽤時,被java的垃圾回收器回收了
⼀句話總結:多例模式的bean對象,spring框架只負責建立,不負責銷燬

Bean標籤屬性

在基於xml的IoC配置中,bean標籤是最基礎的標籤。它表示了IoC容器中的⼀個對象。換句話說,若是⼀個對象想讓spring管理,在XML的配置中都須要使⽤此標籤配置,Bean標籤的屬性以下:app

  • id屬性:⽤於給bean提供⼀個惟⼀標識。在⼀個標籤內部,標識必須惟⼀
  • class屬性:⽤於指定建立Bean對象的全限定類名
  • name屬性:⽤於給bean提供⼀個或多個名稱(別名)。多個名稱⽤空格分隔
  • factory-bean屬性:⽤於指定建立當前bean對象的⼯⼚bean的惟⼀標識。當指定了此屬性以後,class屬性失效
  • factory-method屬性:⽤於指定建立當前bean對象的⼯⼚⽅法,如配合factory-bean屬性使⽤,則class屬性失效。如配合class屬性使⽤,則⽅法必須是static的
  • scope屬性:⽤於指定bean對象的做⽤範圍。一般狀況下就是singleton。當要⽤到多例模式時,能夠配置爲prototype
  • init-method屬性:⽤於指定bean對象的初始化⽅法,此⽅法會在bean對象裝配後調⽤。必須是⼀個⽆參⽅法
  • destory-method屬性:⽤於指定bean對象的銷燬⽅法,此⽅法會在bean對象銷燬前執⾏。它只能爲scope是singleton時起做⽤

DI依賴注⼊的xml配置

  • 依賴注⼊分類框架

    • 按照注⼊的⽅式分類ide

      • 構造函數注⼊:顧名思義,就是利⽤帶參構造函數實現對類成員的數據賦值
      • set⽅法注⼊:它是經過類成員的set⽅法實現數據的注⼊(使⽤最多的)
    • 按照注⼊的數據類型分類函數

      • 基本類型和String:注⼊的數據類型是基本類型或者是字符串類型的數據。
      • 其餘Bean類型:注⼊的數據類型是對象類型,稱爲其餘Bean的緣由是,這個對象是要求出如今IoC容器中的。那麼針對當前Bean來講,就是其餘Bean了
      • 複雜類型(集合類型):注⼊的數據類型是Aarry,List,Set,Map,Properties中的⼀種類型

xml與註解相結合模式

注意:性能

  • 實際企業開發中,純xml模式使⽤已經不多了
  • 引⼊註解功能,不須要引⼊額外的jar
  • xml+註解結合模式,xml⽂件依然存在,因此,springIOC容器的啓動仍然從加載xml開始
  • 哪些bean的定義寫在xml中,哪些bean的定義使⽤註解測試

    第三⽅jar中的bean定義在xml,⽐如德魯伊數據庫鏈接池,⾃⼰開發的bean定義使⽤註解
xml中標籤與註解的對於(IOC)
xml形式 對應的註解形式
標籤 @Component("accountDao"),註解加在類上bean的id屬性內容直接配置在註解後⾯若是不配置,默認定義個這個bean的id爲類的類名⾸字⺟⼩寫;另外,針對分層代碼開發提供了@Componenet的三種別名@Controller、@Service、@Repository分別⽤於控制層類、服務層類、dao層類的bean定義,這四個註解的⽤法徹底⼀樣,只是爲了更清晰的區分⽽已
標籤的scope屬性 @Scope("prototype"),默認單例,註解加在類上
標籤的init- method屬性 @PostConstruct,註解加在⽅法上,該⽅法就是初始化後調⽤的⽅法
標籤的destory- method屬性 @PreDestory,註解加在⽅法上,該⽅法就是銷燬前調⽤的⽅法

Spring IOC高級特性

lazy-Init延遲加載

Bean的延遲加載(延遲建立)

ApplicationContext容器的默認⾏爲是在啓動服務器時將全部 singletonbean提早進⾏實例化。提早實例化意味着做爲初始化過程的⼀部分,ApplicationContext實例會建立並配置全部的singleton bean
⽐如:

<bean id="testBean" class="cn.boc.LazyBean" />
該bean默認的設置爲:
<bean id="testBean" class="cn.boc.LazyBean" lazy-init="false" />

lazy-init="false",⽴即加載,表示在spring啓動時,⽴刻進⾏實例化,若是使用註解則爲@Lazy,默認參數就是true

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
@Lazy
public class BeanExp {
}

若是不想讓⼀個singleton bean 在 ApplicationContext實現初始化時被提早實例化,那麼能夠將bean設置爲延遲實例化

<bean id="testBean" class="cn.boc.LazyBean" lazy-init="false" />

設置 lazy-inittrue的 bean將不會在 ApplicationContext啓動時提早被實例化,⽽是第⼀次向容器經過 getBean索取 bean時實例化的

若是⼀個設置了⽴即加載的 bean1,引⽤了⼀個延遲加載的 bean2 ,那麼 bean1 在容器啓動時被實例化,⽽ bean2 因爲被 bean1 引⽤,因此也被實例化,這種狀況也符合延時加載的 bean 在第⼀次調⽤時才被實例化的規則

也能夠在容器層次中經過在 元素上使⽤ "default-lazy-init" 屬性來控制延時初始化。以下⾯配置:

<beans default-lazy-init="true">
<!-- no beans will be eagerly pre-instantiated... -->
</beans>

若是⼀個 bean 的 scope 屬性爲 scope="pototype" 時,即便設置了 lazy-init="false",容器啓動時也不會實例化bean,⽽是調⽤ getBean ⽅法實例化的

應⽤場景

  • 開啓延遲加載⼀定程度提⾼容器啓動和運轉性能
  • 對於不常使⽤的 Bean設置延遲加載,這樣偶爾使⽤的時候再加載,沒必要要從⼀開始該 Bean就佔⽤資源

FactoryBean和BeanFactory

  • BeanFactory接⼝是容器的頂級接⼝,定義了容器的⼀些基礎⾏爲,負責⽣產和管理Bean的⼀個⼯⼚, 具體使⽤它下⾯的⼦接⼝類型,⽐如ApplicationContext
  • Spring中Bean有兩種,⼀種是普通Bean,⼀種是⼯⼚Bean(FactoryBean)FactoryBean能夠⽣成某⼀個類型的Bean實例(返回給咱們),也就是說咱們能夠藉助於它⾃定義Bean的建立過程
Bean建立的三種⽅式中的靜態⽅法和實例化⽅法和FactoryBean做⽤相似,FactoryBean使⽤較多,尤爲在Spring框架⼀些組件中會使⽤,還有其餘框架和Spring框架整合時使⽤
BeanExp3類
public class BeanExp3 {

    String name;
    String address;
    int type;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "BeanExp3{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", type=" + type +
                '}';
    }
}
MyFactoryBean類
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyFactoryBean implements FactoryBean<BeanExp3> {

    @Value("測試Bean,中環大廈,1")
    public String info;

    @Override
    public BeanExp3 getObject() throws Exception {
        System.out.println("info:" + info);
        BeanExp3 beanExp3 = new BeanExp3();
        String[] array = info.split(",");
        beanExp3.setName(array[0]);
        beanExp3.setAddress(array[1]);
        beanExp3.setType(Integer.valueOf(array[2]));
        return beanExp3;
    }

    @Override
    public Class<?> getObjectType() {
        return BeanExp.class;
    }
}
xml配置
<bean id="BeanExp3" class="com.boc.MyFactoryBean">
<property name="companyInfo" value="測試Bean,中環大廈,1"/>
</bean>
測試,獲取FactoryBean產⽣的對象
Object beanExp3 = appcationContext.getBean("myFactoryBean");
 System.out.println(beanExp3);
測試,獲取FactoryBean,須要在id以前添加「&」
Object beanExp3 = appcationContext.getBean("&myFactoryBean");
 System.out.println(beanExp3);

後置處理器

Spring提供了兩種後處理bean的擴展接⼝,分別爲 BeanPostProcessorBeanFactoryPostProcessor,二者在使⽤上是有所區別的

⼯⼚初始化(BeanFactory)—> Bean對象

在BeanFactory初始化以後可使⽤BeanFactoryPostProcessor進⾏後置處理作⼀些事情

在Bean對象實例化(並非Bean的整個⽣命週期完成)以後可使⽤BeanPostProcessor進⾏後置處理作⼀些事情

注意:對象不⼀定是springbean,⽽springbean⼀定是個對象

SpringBean的⽣命週期
image.png

BeanPostProcessor

BeanPostProcessor是針對Bean級別的處理,能夠針對某個具體的Bean
image.png
該接⼝提供了兩個⽅法,分別在Bean的初始化⽅法前和初始化⽅法後執⾏,具體這個初始化⽅法指的是   什麼⽅法,相似咱們在定義bean時,定義了init-method所指定的⽅法

定義⼀個類實現了BeanPostProcessor,默認是會對整個Spring容器中全部的bean進⾏處理。若是要對     具體的某個bean處理,能夠經過⽅法參數判斷,兩個類型參數分別爲Object和String,第⼀個參數是每一個bean的實例,第⼆個參數是每一個bean的name或者id屬性的值。因此咱們能夠經過第⼆個參數,來判斷咱們將要處理的具體的bean。

注意:處理是發⽣在Spring容器的實例化和依賴注⼊以後。

BeanFactoryPostProcessor

BeanFactory級別的處理,是針對整個Bean的⼯⼚進⾏處理,典型應
⽤:PropertyPlaceholderConfigurer
image.png
此接⼝只提供了⼀個⽅法,⽅法參數爲ConfigurableListableBeanFactory,該參數類型定義了⼀些⽅法
image.png
其中有個⽅法名爲getBeanDefinition的⽅法,咱們能夠根據此⽅法,找到咱們定義bean的BeanDefinition對象。而後咱們能夠對定義的屬性進⾏修改,如下是BeanDefinition中的⽅法
image.png
⽅法名字相似咱們bean標籤的屬性,setBeanClassName對應bean標籤中的class屬性,因此當咱們拿到BeanDefinition對象時,咱們能夠⼿動修改bean標籤中所定義的屬性值。

BeanDefinition對象:咱們在XML中定義的bean標籤,Spring解析bean標籤成爲⼀個JavaBean,這個JavaBean就是BeanDefinition

注意:調⽤ BeanFactoryPostProcessor ⽅法時,這時候bean尚未實例化,此時 bean 剛被解析成BeanDefinition對象

相關文章
相關標籤/搜索