最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Sprin中Bean的順序使用及說明

 更新時(shí)間:2024年05月21日 11:17:44   作者:影??  
這篇文章主要介紹了Sprin中Bean的順序使用及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、Bean的加載順序

spring容器載入bean順序是不確定的,在一定的范圍內(nèi)bean的加載順序可以控制。

在這里插入圖片描述

spring容器載入bean雖然順序不確定,但遵循一定的規(guī)則:

1、按照字母順序加載(同一文件夾下按照字母數(shù)序;不同文件夾下,先按照文件夾命名的字母順序加載)

2、不同的bean聲明方式不同的加載時(shí)機(jī),順序總結(jié):@ComponentScan > @Import > @Bean

這里的ComponentScan指@ComponentScan及其子注解,Bean指的是@configuration + @bean   

同時(shí)需要注意的是:   

  • (1)Component及其子注解申明的bean是按照字母順序加載的   
  • (2)@configuration + @bean是按照定義的順序依次加載的   
  • (3)@import的順序,就是bean的加載順序   
  • (4)在xml中,通過<bean id="">方式聲明的bean也是按照代碼的編寫順序依次加載的   
  • (5)同一類中加載順序:Constructor >> @Autowired >> @PostConstruct >> @Bean   
  • (6)同一類中加載順序:靜態(tài)變量 / 靜態(tài)代碼塊 >> 構(gòu)造代碼塊 >> 構(gòu)造方法(需要特別注意的是靜態(tài)代碼塊的執(zhí)行并不是優(yōu)先所有的bean加載,只是在同一個(gè)類中,靜態(tài)代碼塊優(yōu)先加載) 

特別情況下,如果想手動(dòng)控制部分bean的加載順序,有如下方法:

方法1:構(gòu)造方法依賴 (推薦)

@Component
public class CDemo1 {
    private String name = "cdemo 1";

    public CDemo1(CDemo2 cDemo2) {
        System.out.println(name);
    }
}
@Component
public class CDemo2 {
    private String name = "cdemo 2";

    public CDemo2() {
        System.out.println(name);
    }
}

CDemo2在CDemo1之前被初始化。

限制

要有注入關(guān)系,如:CDemo2通過構(gòu)造方法注入到CDemo1中,若需要指定兩個(gè)沒有注入關(guān)系的bean之間優(yōu)先級(jí),則不太合適(比如我希望某個(gè)bean在所有其他的Bean初始化之前執(zhí)行)

循環(huán)依賴問題,如過上面的CDemo2的構(gòu)造方法有一個(gè)CDemo1參數(shù),那么循環(huán)依賴產(chǎn)生,應(yīng)用無法啟動(dòng)

另外一個(gè)需要注意的點(diǎn)是,在構(gòu)造方法中,不應(yīng)有復(fù)雜耗時(shí)的邏輯,會(huì)拖慢應(yīng)用的啟動(dòng)時(shí)間

方法2:參數(shù)注入

在@Bean標(biāo)注的方法上,如果你傳入了參數(shù),springboot會(huì)自動(dòng)會(huì)為這個(gè)參數(shù)在spring上下文里尋找這個(gè)類型的引用。并先初始化這個(gè)類的實(shí)例。

利用此特性,我們也可以控制bean的加載順序。

在這里插入圖片描述

以上結(jié)果,beanB先于beanA被初始化加載。

需要注意的是,springboot會(huì)按類型去尋找。如果這個(gè)類型有多個(gè)實(shí)例被注冊(cè)到spring上下文,那你就需要加上@Qualifier(“Bean的名稱”)來指定

方法3:@Autowired 注入到所需的服務(wù)中

跟在xml配置中寫 ref差不多的功能 spring 會(huì)解析到這個(gè)會(huì)依賴springBeanManager 所以會(huì)先加載springBeanManager

@Component
public class SystemInit {

   @Autowired
    private SpringBeanManager springBeanManager;

    @PostConstruct
    public void init() {
        //初始化 script job  bean
        GroovyBeanInit.InitScriptJob();
    }
}

方法4:@DependsOn(“xxx”)

沒有直接的依賴關(guān)系的,可以通過@DependsOn注解,我們可以在bean A上使用@DependsOn注解 ,告訴容器bean B應(yīng)該優(yōu)先被加載初始化。

不推薦的原因:這種方法是通過bean的名字(字符串)來控制順序的,如果改了bean的類名,很可能就會(huì)忘記來改所有用到它的注解,那就問題大了。

當(dāng)一個(gè)bean需要在另一個(gè)bean實(shí)例化之后再實(shí)例化時(shí),可使用這個(gè)注解。

@Component("dependson02")
public class Dependson02 {
 
    Dependson02(){
        System.out.println(" dependson02 Success ");
    }
}
@Component
@DependsOn("dependson02")
public class Dependson01 {
 
    Dependson01(){
        System.out.println("Dependson01 success");
    }
}

執(zhí)行結(jié)果:

結(jié)果:

dependson02 Success 

Dependson01 success

方法5:BeanDefinitionRegistryPostProcessor接口

通過實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口,在postProcessBeanDefinitionRegistry方法中通過BeanDefinitionRegistry獲取到所有bean的注冊(cè)信息,將bean保存到LinkedHashMap中,并從BeanDefinitionRegistry中刪除,然后將保存的bean定義排序后,重新再注冊(cè)到BeanDefinitionRegistry中,即可實(shí)現(xiàn)bean加載順序的控制。

/**
 *配置類
 */
@Configuration
@ComponentScan(basePackages = "demo")
public class AppConfig extends WebMvcConfigurationSupport {

	/**
	 * 注冊(cè)用于控制bean加載順序的處理器
	 * @return
	 */
	@Bean
	public static DemoProcessor demoProcessor() {
		return new DemoProcessor();
	}
}

/**
 *
 */
public class DemoProcessor implements BeanDefinitionRegistryPostProcessor{

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		String[] beanDefinitionNames = registry.getBeanDefinitionNames();
		int index = 0;
		//保留前n個(gè)關(guān)鍵bean的順序
		for(;index<beanDefinitionNames.length;index++) {
			if(AppConfig.class.getName().equals(registry.getBeanDefinition(beanDefinitionNames[index]).getBeanClassName())) {
				break;
			}
		}
		Map<String, BeanDefinition> beans = new LinkedHashMap<>(beanDefinitionNames.length-index);
		for(;index<beanDefinitionNames.length;index++) {
			BeanDefinition beanDefinition = registry.getBeanDefinition(beanDefinitionNames[index]);
			beans.put(beanDefinitionNames[index], beanDefinition);
			registry.removeBeanDefinition(beanDefinitionNames[index]);
		}
		//TODO ...排序邏輯,注意beans中可能還包含有其他spring自身定義的bean
		List<String> orderdBeanNames = new ArrayList<>();
		//將排好序的bean再次注冊(cè)到容器中
		orderdBeanNames.forEach(beanName->{
			registry.registerBeanDefinition(beanName, beans.get(beanName));
		});
	}
}

注意:

執(zhí)行順序:Constructor > @Autowired > @PostConstruct

所以正常情況下,所有的bean都已經(jīng)執(zhí)行了構(gòu)造器Constructor,也就是bean都已經(jīng)存在容器中了。

也就是正常情況下,都是可以正常執(zhí)行了。

Autowired為null的情況如下:

(1)該類沒有托管給spring 管理

一般在類的上面添加@Component 就可以了

(2)不能new出來的實(shí)例,

例如:A a = new A();//new的對(duì)象不會(huì)交給Spring容器管理, 所以是不行的

特殊情況:@Configuration + @Bean 這種方式是可以的

二、Bean的執(zhí)行順序

注解@Order或者接口Ordered的作用是定義Spring IOC容器中Bean的執(zhí)行順序的優(yōu)先級(jí),而不是定義Bean的加載順序,Bean的加載順序不受@Order或Ordered接口的影響。

特別介紹

  • @PropertySource:用于注解類,告訴當(dāng)前類使用什么配置文件,配置文件必須是.property或者.xml類型。
@PropertySource(value = {"classpath:config/user1.properties","classpath:config/user2.properties"})
  • @ImportResource:通過配置文件注入bean,用于注解主配置類,導(dǎo)入一個(gè)或多個(gè)定義bean的配置文件,配置文件必須是.xml類型。
@ImportResource(value = {"classpath:/beans.xml"})
@SpringBootApplication(scanBasePackages = {"team.seagull.client"})
public class DeployApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeployApplication.class, args);
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 5種Java經(jīng)典創(chuàng)建型模式詳解

    5種Java經(jīng)典創(chuàng)建型模式詳解

    這篇文章主要為大家詳細(xì)介紹了5種Java經(jīng)典創(chuàng)建型模式,感興趣的小伙伴們可以參考一下
    2016-03-03
  • Java實(shí)現(xiàn)文件上傳的方法總結(jié)

    Java實(shí)現(xiàn)文件上傳的方法總結(jié)

    這篇文章主要為大家介紹了三種Java實(shí)現(xiàn)文件上傳的方法,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的借鑒價(jià)值,感興趣的可以了解一下
    2023-04-04
  • Java實(shí)現(xiàn)浪漫流星表白的示例代碼

    Java實(shí)現(xiàn)浪漫流星表白的示例代碼

    本文將利用Java語言實(shí)現(xiàn)浪漫流星表白,可以實(shí)現(xiàn)這些功能:播放音樂、自定義流星數(shù)量、飛行速度、光暈大小、流星大小,自定義表白話語,感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • idea開啟mybatis控制臺(tái)SQL日志打印的代碼示例

    idea開啟mybatis控制臺(tái)SQL日志打印的代碼示例

    本文主要介紹了idea開啟mybatis控制臺(tái)SQL日志打印的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • MyBatis ResultMap 的基本用法示例詳解

    MyBatis ResultMap 的基本用法示例詳解

    在MyBatis 中,resultMap 用于定義數(shù)據(jù)庫查詢結(jié)果到Java對(duì)象屬性的映射關(guān)系,本文給大家介紹MyBatis ResultMap的基本用法,感興趣的朋友一起看看吧
    2025-06-06
  • java使用JDBC動(dòng)態(tài)創(chuàng)建數(shù)據(jù)表及SQL預(yù)處理的方法

    java使用JDBC動(dòng)態(tài)創(chuàng)建數(shù)據(jù)表及SQL預(yù)處理的方法

    這篇文章主要介紹了java使用JDBC動(dòng)態(tài)創(chuàng)建數(shù)據(jù)表及SQL預(yù)處理的方法,涉及JDBC操作數(shù)據(jù)庫的連接、創(chuàng)建表、添加數(shù)據(jù)、查詢等相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-08-08
  • 詳解Java?中的函數(shù)式接口

    詳解Java?中的函數(shù)式接口

    這篇文章主要為大家介紹了Java中的函數(shù)式接口,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助<BR>
    2021-12-12
  • 關(guān)于Java垃圾回收開銷降低的幾條建議

    關(guān)于Java垃圾回收開銷降低的幾條建議

    垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供的一種用于在空閑時(shí)間不定時(shí)回收無任何對(duì)象引用的對(duì)象占據(jù)的內(nèi)存空間的一種機(jī)制,下面這篇文章主要介紹了關(guān)于Java垃圾回收開銷降低的幾條建議,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • mybatis-plus實(shí)現(xiàn)打印完整sql語句

    mybatis-plus實(shí)現(xiàn)打印完整sql語句

    這篇文章主要介紹了mybatis-plus實(shí)現(xiàn)打印完整sql語句方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • SWT JFace Bookmark 制作

    SWT JFace Bookmark 制作

    SWT JFace Bookmark 制作
    2009-06-06

最新評(píng)論

张掖市| 六盘水市| 阆中市| 磐安县| 从江县| 永春县| 天水市| 孙吴县| 宣汉县| 绵阳市| 克什克腾旗| 海淀区| 达拉特旗| 上蔡县| 洪泽县| 沛县| 渝北区| 祁东县| 南川市| 溆浦县| 高要市| 东港市| 措美县| 秭归县| 铁力市| 酒泉市| 大竹县| 扬州市| 吉首市| 乌拉特前旗| 罗城| 房产| 剑阁县| 崇文区| 汤原县| 宜州市| 沿河| 虹口区| 临颍县| 英吉沙县| 梧州市|