#Spring:定義Bean加載順序

 

Spring容器載入bean順序是不肯定的,Spring框架沒有約定特定順序邏輯規範。但Spring保證若是A依賴B(如beanA中有@Autowired B的變量),那麼B將先於A被加載。spring

邏輯判斷

在業務層本身控制A,B的初始化順序框架

構造方法依賴

@Component
publicclass DemoA {

    private String name = "demo A";

    public DemoA(DemoB demoB) {
        System.out.println(name);
    }
}

@Component
publicclass DemoB {

    private String name = "demo B";

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

這個時候構造A的時候就會先去構造B

使用@DependsOn

Spring 中的@DependsOn能夠保證被依賴的bean先於當前bean被容器建立ide

@DependsOn註解能夠定義在類和方法上,意思是我這個組件要依賴於另外一個組件,也就是說被依賴的組件會比該組件先註冊到IOC容器中。post

類上使用註解:

package com.spring.master.spring;

import org.springframework.stereotype.Component;

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:55
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
@Component
public class EventSource {

    public EventSource(){
        System.out.println("事件源建立");
    }
}


package com.spring.master.spring.dependson;

import org.springframework.stereotype.Component;

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:56
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
@Component
public class EventListener {

    public EventListener(){
        System.out.println("監聽器建立");
    }
}

package com.spring.master.spring.dependson;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:57
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
@Configuration
@ComponentScan(basePackages = "com.spring.master.spring")
public class SpringConfig {


}


啓動服務:
事件源建立
監聽器建立

備註:
Spring默認掃描包時會根據文件在文件夾的位置前後順序掃描加載

********************************************************************************************

使用@DependsOn註解:

package com.spring.master.spring;

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

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:55
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
@Component
@DependsOn(value = {"eventListener"})
public class EventSource {

    public EventSource(){
        System.out.println("事件源建立");
    }
}

啓動服務:
監聽器建立
事件源建立
方法上使用註解:

package com.spring.master.spring;

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

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:55
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
//@Component
//@DependsOn(value = {"eventListener"})
public class EventSource {

    public EventSource(){
        System.out.println("事件源建立");
    }
}


package com.spring.master.spring.dependson;

import org.springframework.stereotype.Component;

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:56
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
//@Component
public class EventListener {

    public EventListener(){
        System.out.println("監聽器建立");
    }
}


package com.spring.master.spring.dependson;

import com.spring.master.spring.EventSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

/**
 * @author Huan Lee
 * @version 1.0
 * @date 2020-09-22 15:57
 * @describtion 業精於勤,荒於嬉;行成於思,毀於隨。
 */
@Configuration
@ComponentScan(basePackages = "com.spring.master.spring")
public class SpringConfig {

    @Bean
    @DependsOn(value = {"eventListener"})
    public EventSource eventSource(){
        return new EventSource();
    }

    @Bean
    public EventListener eventListener(){
        return new EventListener();
    }

}


啓動服務輸出:
監聽器建立
事件源建立

BeanFactoryPostProcessor

容器加載bean以前:BeanFactoryPostProcessor 能夠容許咱們在容器加載任何bean以前修改應用上下文中的BeanDefinitionui

在本例中,就能夠把A的初始化邏輯放在一個 BeanFactoryPostProcessor 中。
@Component
public class ABeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    A.initA();
  }
}

這種方式把A中的初始化邏輯放到了加載bean以前,很適合加載系統全局配置,可是這種方式中初始化邏輯不能依賴bean的狀態。

BeanPostProcessor

@Component
publicclass HDemo1 {
    private String name = "h demo 1";

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

@Component
publicclass HDemo2 {
    private String name = "h demo 2";

    public HDemo2() {
        System.out.println(name);
    }
}
@Component
publicclass DemoBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements BeanFactoryAware {
    private ConfigurableListableBeanFactory beanFactory;
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            thrownew IllegalArgumentException(
                    "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    @Override
    @Nullable
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 在bean實例化以前作某些操做
        if ("HDemo1".equals(beanName)) {
            HDemo2 demo2 = beanFactory.getBean(HDemo2.class);
        }
        return null;
    }
}

請將目標集中在postProcessBeforeInstantiation,這個方法在某個 bean 的實例化以前,會被調用,這就給了咱們控制 bean 加載順序的機會。this

相關文章
相關標籤/搜索