#Spring:定义Bean加载顺序

原创
09/22 16:35
阅读数 3.3K

 

Spring容器载入bean顺序是不确定的,Spring框架没有约定特定顺序逻辑规范。但Spring保证如果A依赖B(如beanA中有@Autowired B的变量),那么B将先于A被加载。

逻辑判断

在业务层自己控制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被容器创建

@DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中。

类上使用注解:

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之前修改应用上下文中的BeanDefinition

在本例中,就可以把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 加载顺序的机会。

 

 

 

 

 

 

 

 

展开阅读全文
打赏
2
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
2
分享
返回顶部
顶部