Spring5源碼深度解析(一)之理解Configuration註解

代碼地址:https://github.com/showkawa/spring-annotation/tree/master/src/main/java/com/brian

1.Spring體繫結構

1.1、Spring Core:主要組件是BeanFactory,創建JavaBean的工廠,使用控制反轉(IOC) 模式  將應用程序的配置和依賴性規範與實際的應用程序代碼分開。

1.2、Spring AOP:集成了面向切面的編程功能(AOP把一個業務流程分成幾部分,例如權限檢查、業務處理、日誌記錄,每個部分單獨處理,然後把它們組裝成完整的業務流程。每個部分被稱為切面),

 可以將聲明性事物管理集成到應用程序中。

1.3、Spring Cntext:一個核心配置文件,為Spring框架提供上下文信息。

1.4、Spring Do:Spring操作數據庫的模塊。

1.5、Spring ORM:Spring集成了各種orm(object relationship mapping 對象關係映射)框架的模塊,集成mybatis

1.6、Spring Web集成各種優秀的web層框架的模塊(Struts、Springmvc)

1.7、Spring web MVC:Spring web層框架

 2.Configuration註解分析內容(@Configuration,@ComponentScan,@Scope,@Lazy)

2.1 @Configuration

 @Configuration用於定義配置類,可替換xml配置文件,被註解的類內部包含有一個或多個被@Bean註解的方法,這些方法將會被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進行掃描,並用於構建bean定義,初始化Spring容器。

2.1.1 @Configuration標註在類上,相當於把該類作為spring的xml配置文件中的<beans>,作用為:配置spring容器(應用上下文)

@Configuration
public class MainConfigOfLifeCycle { }

//測試方法

public static void main(String[] args) {
ApplicationContext acac =
new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("ioc容器創建成功");

//關閉ioc容器
((AnnotationConfigApplicationContext) acac).close();
}
 

相當於spring的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"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-5.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-5.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-5.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-5.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-5.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-5.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-5.0.xsd" default-lazy-init="false">


</beans>

2.2 @ComponentScan用法 

 ComponentScan字面意思就是組件掃描,就是根據定義的掃描路徑,把符合掃描規則的類裝配到spring容器中

  2.2.1 ComponentScan參數說明

/*
* @ComponentScan
* value:只當於掃描的的包
* excludeFilters = 指定掃描的時候按照什麼規則排除哪些組件
* includeFilters = 指定掃描的時候只需要包含哪些組件
* Filter.ANNOTATION:按照註解
* Filter.ASSIGNABLE_TYPE: 按照給定的類型
* */

FilterType 有五種類型

ANNOTATION:註解類型

ASSIGNABLE_TYPE:ANNOTATION:指定的類型

ASPECTJ:按照Aspectj的表達式,基本上不會用到

REGEX:按照正則表達式

CUSTOM:自定義規則

package com.brian.config;

import com.brian.bean.Alan;
import com.brian.bean.Brian;
import com.brian.bean.BrianBeanFactory;
import com.brian.bean.Person;
import com.brian.condition.BrianCondition;
import com.brian.condition.BrianSelector;
import com.brian.service.BookService;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;

@Configuration //告訴spring這是一個配置類
/*
* @ComponentScan
*   value:只當於掃描的的包
*   excludeFilters = 指定掃描的時候按照什麼規則排除哪些組件
*   includeFilters = 指定掃描的時候只需要包含哪些組件
*   Filter.ANNOTATION:按照註解
*   Filter.ASSIGNABLE_TYPE: 按照給定的類型
* */

@ComponentScans(value = {
        @ComponentScan(value = "com.brian",includeFilters = {
//                @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
//                @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}),
                @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {BrianTypeFilter.class})
        },useDefaultFilters = false)
})
@Import({Brian.class,Alan.class,BrianSelector.class})
public class MainConfig {

    @Bean("person") //給容器中註冊一個Bean;類型為返回值的類型;id默認是方法名作為id
    public Person person(){
        return new Person("Alan",18);
    }


    /*
    * @Conditional() 按照條件註冊
    *
    * */
    @Conditional({BrianCondition.class})
    @Bean("person01")
    public Person person01() {
        return new Person("Brian",17);
    }

    @Conditional({BrianCondition.class})
    @Bean("person02")
    public Person person02() {
        return new Person("wenTao",19);
    }

    /*
    *
    *給容器中註冊組件
    * 1,包掃描+ 組件標註註解(@Controller/@Service/@Repository/@Component)[自己寫的方法]
    * 2, @Bean [導入的第三方包裏面的組件]
    * 3,@Import [快速的給容器導入一個組件]
    *       1.@Import(要導入的組件class)
    *       2.ImportSelector:返回需要導入的組件的全類名數組
    *       3.ImportBeanDefinitionRegistrar: 手動註冊bean到容器
    *  4. 使用Spring提供的FactoryBean
    * */
    @Bean
    public BrianBeanFactory brianBeanFactory() {
        return new BrianBeanFactory();
    }

}

2.3 @Scope

默認情況Spring容器是單例的

singleton單例模式:全局有且僅有一個實例。

prototype原型模式:每次獲取Bean的時候都會有一個新的實例。

request

request表示針對每次請求都會產生一個新的Bean對象,並且該Bean對象僅在當前Http請求內有效。

session

session作用域表示煤氣請求都會產生一個新的Bean對象,並且該Bean僅在當前Http session內有效。

測試@Scopeprototype原型模式

Configuration配置類

@Configuration
@ComponentScan("com.brian.bean")
public class MainConfigOfLifeCycle {
    @Scope("prototype")
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Alan getAlan () {
        return new Alan();
    }
}

測試類

public class MainTest {
    public static void main(String[] args) {
         /*ApplicationContext acac =
                 new AnnotationConfigApplicationContext(MainConfig.class);*/
         ApplicationContext acac =
                 new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("ioc容器創建成功");
        Alan alan1 =  acac.getBean(Alan.class);
        Alan alan2 =  acac.getBean(Alan.class);
        System.out.println("比較兩個Alan實例: " + (alan1 == alan2));

        //關閉ioc容器
        ((AnnotationConfigApplicationContext) acac).close();
    }
}

2.4 @Lazy

Lazy表示為懶加載,當真正需要引用獲取的時候才會被加載

True 表示為懶加載 false表示為在IOC容器加載的時候被創建。

 

測試@Lazy(false)餓漢模式加載

Configuration配置類

@Configuration
@ComponentScan("com.brian.bean")
public class MainConfigOfLifeCycle {
    //@Scope("prototype")
    @Lazy(false)
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Alan getAlan () {
        return new Alan();
    }


}

測試類

public class MainTest {
    public static void main(String[] args) {
         /*ApplicationContext acac =
                 new AnnotationConfigApplicationContext(MainConfig.class);*/
         ApplicationContext acac =
                 new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("ioc容器創建成功");
      //  Alan alan1 =  acac.getBean(Alan.class);
       // Alan alan2 =  acac.getBean(Alan.class);
        //System.out.println("比較兩個Alan實例: " + (alan1 == alan2));

        //關閉ioc容器
        ((AnnotationConfigApplicationContext) acac).close();
    }
}

 看下結果會發現在餓漢模式下,即使沒用使用AnnotationConfigApplicationContext.getBean()獲取對象,對象也被加載進了IOC容器

測試@Lazy默認懶加載

 Configuration配置類

@Configuration
@ComponentScan("com.brian.bean")
public class MainConfigOfLifeCycle {
    //@Scope("prototype")
    @Lazy
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Alan getAlan () {
        return new Alan();
    }


}

測試類保持不表

測試結果中,沒有輸出Alan這個對象創建和銷毀的打印信息

 

【精選推薦文章】

自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"