Spring自动装配订单和@PostConstruct

时间:2016-06-28 06:11:11

标签: java spring spring-bean

我对Spring中的自动布线顺序和@PostConstruct逻辑有疑问。例如,下面的演示代码我有一个主要的Spring Boot类:

@SpringBootApplication
public class Demo1Application {

    @Autowired
    BeanB beanb;

    public static void main(String[] args) {
        SpringApplication.run(Demo1Application.class, args);
    }
}

和2 @Service定义:

@Service
public class BeanB {

    @Autowired
    private BeanA beana ;

    @PostConstruct
    public void init(){
        System.out.println("beanb is called");
    }

    public void printMe(){
        System.out.println("print me is called in Bean B");
    }
}

@Service
public class BeanA {

    @Autowired
    private BeanB b;

    @PostConstruct
    public void init(){
        System.out.println("bean a is called");
        b.printMe();
    }
}

我有以下输出:

  

bean a被称为

     

打印我在Bean B中调用

     

beanb被称为


我的问题是如何像上面的场景一样一步一步地进行自动装配? printMe()如何调用beanb方法而不首先调用@PostConstruct

2 个答案:

答案 0 :(得分:14)

下面应该是可能的序列

  1. beanb开始获得自动装配
  2. Beanb的课程初始化期间,beana开始获得自动装配
  3. 一旦beana被创建,@PostConstruct即被称为init()的beana被称为
  4. init()内,System.out.println("bean a is called");被称为
  5. 然后调用b.printMe();导致System.out.println("print me is called in Bean B");执行
  6. beana完成@PostConstructinit() beanb被称为
  7. 然后调用System.out.println("beanb is called");
  8. 理想情况下,eclipse中的调试器可以更好地观察到它。

    Spring reference manual解释了如何解决循环依赖关系。首先实例化bean,然后相互注入。

答案 1 :(得分:5)

你的答案是正确的,如你在问题中所示。

现在获得符号@Autowired的概念。在完成类加载后,所有@Autowired对象都被初始化并加载到内存中。

现在这是您的SpringBootApplication

@SpringBootApplication
public class Demo1Application {
    @Autowired
    BeanB beanb;   // You are trying to autowire a Bean class Named BeanB.

在上面的控制台应用程序中,您尝试自动装配并注入BeanB类型的对象。

现在,这是您对BeanB

的定义
@Service
public class BeanB {

    @Autowired
    private BeanA beana ;

BeanB类中,您尝试注入类BeanA的对象,该对象也在您的控制台项目中定义。

因此,在Demo1Application中注入类BeanB的对象时,必须注入类BeanA的对象。 现在BeanA类对象首先被创建。

现在,如果您看到了您的班级BeanA

的定义
 @Service
public class BeanA {

    @Autowired
    private BeanB b;

    @PostConstruct   // after Creating bean init() will be execute.
    public void init(){
        System.out.println("bean a is called");
        b.printMe();
    }
}

因此,在注入Object BeanA方法之后,将使用@PostContruct注释执行。

因此,执行流程将是......

System.out.println("bean a is called");
System.out.println("print me is called in Bean B");
System.out.println("beanb is called");