Spring IOC 註解 — @Bean,@Scope 和 @Lazy

Spring可以做很多事情,爲企業級開發提供了豐富的功能,但是這些功能都依賴於它的兩個核心特性:依賴注入(DI)或控制反轉(IOC)和麪向切面編程(AOP)。如果說Spring IOC容器將開發人員從對Bean(實例)的管理的繁重任務中脫離出來,那麼Spring提供的註解則將開發人員從Spring中繁複的xml配置中解脫出來。

Spring爲我們提供了很多註解,用於將我們自己寫的組件交給Spring IOC容器管理,比如:我們可以使用@Controller註解標註該類爲一個控制器,使用@Service標註一個類爲業務邏輯類,@Repository標註一個類爲數據庫訪問類,@Component標註一個類爲組件,@Configuration標註該類是一個配置類。但是對於第三方框架或者jar包,這些組件就無能爲力了,不過Spring爲我們準備了其他註解,將第三方無法使用上述註解的類交給Spring管理,比如:@Bean,@Import等

@Bean註解的使用

1.@Bean註解用於@Configration註解的類的方法上,用於創建一個Spring IOC管理的Bean,默認情況下,被創建的bean在Spring中的名稱爲方法名,如下代碼所示,創建的bean的名稱爲printComponent:

@Bean
public PrintComponent printComponent() {
    return new PrintComponent();
}

2.Spring爲@Bean註解提供了 value和name屬性,它們的類型爲字符串數組,我們可以使用這兩個屬性爲該bean指定名稱,但是這兩個直接不能同時使用,只能使用其中的一個。 如果指定了多個名稱,在使用getBeanDefinitionNames方法打印Bean名稱時,只打印第一個名稱。代碼示例如下:

@Bean(name="print")
public PrintComponent printComponent() {
    return new PrintComponent();
}
//一個bean實例兩個名稱,使用context.getBean("printComponent")和context.getBean("print")獲取的是一個實例
@Bean(name={"print","printComponent"})
public PrintComponent printComponent() {
    return new PrintComponent();
}
//一個bean實例兩個名稱,使用context.getBean("printComponent")和context.getBean("print")獲取的是一個實例
@Bean(value={"print1","printComponent2"})
public PrintComponent printComponent() {
    return new PrintComponent();
}

將Bean交給Spring IOC之後,由IOC負責對Bean的實例化,可能我們需要在Bean實例化之後(構造方法調用之後)和容器關閉之前做一些操作。此時,我們可以使用@Bean註解的initMethod方法爲該實例指定一個初始化方法,使用destroyMethod爲該實例指定一個銷燬方法。如下代碼,initMethod方法會在實例化之後調用,destoryMethod方法會在IOC容器銷燬時被調用

public class PrintComponent {
	
    public PrintComponent() {
	System.out.println("構造方法");
    }
	
    public void initMethod() {
        System.out.println("打印之前,檢查是否準備好石墨和紙張");
    }

    public void printContent() {
        System.out.println("打印中");
    }

    public void destoryMethod() {
        System.out.println("報警:已經打印完成,可以取出打印的紙張");
    }
}
@Bean(value="print",initMethod ="initMethod", destroyMethod="destoryMethod")
public PrintComponent printComponent() {
    return new PrintComponent();
}

@Scope註解

默認情況下交給Spring管理的Bean都是單例的,如果我們想使用多例模式的Bean,則可以使用@Scope註解。@Scope註解用於爲Bean指定作用域。Spring中的Bean有四種作用域:默認爲singleton:單實例的(默認值):ioc容器啓動會調用方法創建對象放到ioc容器中。以後每次獲取就是直接從容器(map.get())中拿,prototype:多實例的:ioc容器啓動並不會去調用方法創建對象放在容器中。每次獲取的時候纔會調用方法創建對象;request:同一次請求創建一個實例,session:同一個session創建一個實例。值得注意的是如果@Bean中包含initMethd屬性和destroyMethod屬性,多例的Bean只會指定initMethod方法中指定的方法,destroyMethod中指定的方法不會執行。

@Scope("prototype")
@Bean(value="print")
public PrintComponent printComponent() {
    return new PrintComponent();
}

@Lazy註解

默認情況下Spring在容器啓動的時候創建對象;如果我們不想讓容器啓動的時候就創建對象,而是在獲取實例的時候才創建對象,則可以使用@Lazy註解:

@Lazy
@Bean(value="print", initMethod = "initMethod",destroyMethod="destoryMethod")
public PrintComponent printComponent() {
    return new PrintComponent();
}

@PostConstruct與@PreDestroy

前面我們提到我們可以使用@Bean註解的initMethod方法爲該實例指定一個初始化方法,使用destroyMethod爲該實例指定一個銷燬方法。這兩個方法分別在實例創建之後和容器銷燬之前被調用,除此之外,我們還可以在Bean的方法上標註@PostConstruct和@PreDestroy註解。他們是JSR250提供的兩個註解,@PostConstruct在實例創建之後被調用,@PreDestroy在容器被銷燬之前調用。代碼如下:

public class PrintComponent {
    public PrintComponent() {
        System.out.println("構造方法");
    }
    @PostConstruct
    public void initMethod() {
        System.out.println("打印之前,檢查是否準備好石墨和紙張");
    }
    public void printContent() {
        System.out.println("打印中");
    }
    @PreDestroy
    public void destoryMethod() {
        System.out.println("報警:已經打印完成,可以取出打印的紙張");
    }
}
@Bean(value="print")
public PrintComponent printComponent() {
    return new PrintComponent();
}

 

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