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