为什么@Configuration注解的类中,@Bean方法可以相互调用,不会产生死循环或不同的bean?

样例代码:

@Configuration
public class SpringTest {

    @Test
    public void test() throws IOException {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
        ac.register(SpringTest.class);
        ac.refresh();

        MyBean bean = ac.getBean(MyBean.class);
        System.out.println(bean);
        System.out.println(this);

        System.in.read();
    }

    @Bean
    public MyBean myBean() {
        System.out.println("Create MyBean");
        System.out.println(this);
        System.out.println();
        return new MyBean();
    }

    @Bean
    public MyBean2 myBean2() {
        System.out.println("Create MyBean2");
        System.out.println(myBean()); // Dead loop?
        System.out.println(this);
        System.out.println();
        return new MyBean2();
    }
}

 

执行结果:

Create MyBean
com.lance.test.spring.SpringTest$$EnhancerBySpringCGLIB$$9e451e89@c8c12ac

Create MyBean2
com.lance.test.spring.MyBean@2a65fe7c
com.lance.test.spring.SpringTest$$EnhancerBySpringCGLIB$$9e451e89@c8c12ac

com.lance.test.spring.MyBean@2a65fe7c
com.lance.test.spring.SpringTest@5b7a5baa

 

可以看出,myBean方法只运行了一次。  
原因是,@Configuration注解的类,spring创建了SpringTest的代理类,覆写了myBean()和myBean2()方法。

 

class SpringTest$$EnhancerBySpringCGLIB$$9e451e89 extends SpringTest {
    
    //...
  
    
    public final MyBean2 myBean2() {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0; 
        if (methodInterceptor == null) {
            SpringTest$$EnhancerBySpringCGLIB$$9e451e89.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {
            return (MyBean2)methodInterceptor.intercept(this, CGLIB$myBean2$1$Method, CGLIB$emptyArgs, CGLIB$myBean2$1$Proxy); 
        }
        return super.myBean2(); 
    }

    public final MyBean myBean() {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) { 
            SpringTest$$EnhancerBySpringCGLIB$$9e451e89.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        } 
        if (methodInterceptor != null) {
            return (MyBean)methodInterceptor.intercept(this, CGLIB$myBean$2$Method, CGLIB$emptyArgs, CGLIB$myBean$2$Proxy);
        } 
        return super.myBean();
    }
    
    // ...

}

 

(1)调用myBean()时,先判断是否初始化MethodInterceptor。若未初始化,则直接调用父类SpringTest.myBean();若已初始化,则调用methodInterceptor.intercept并返回相应的数据  
(2)调用myBean2()时,也是先判断MethodInterceptor,但在调用myBean()方法时,实际上调用的是代理类的myBean(),所以循环调用不会产生死循环  

 

类似于以下的代码

public class Demo {

    public static void main(String[] args) {
        new A().test();
        System.out.println();
        new B().test();
    }
}

class A {

    public void test() {
        m1();
        m2();
    }

    public void m1() {
        System.out.println("A m1");
    }

    public void m2() {
        System.out.println("A m2");
        m1();
    }
}


class B extends A {

    @Override
    public void m1() {
        System.out.println("B m1");
        super.m1();
    }

    @Override
    public void m2() {
        System.out.println("B m2");
        super.m2();
    }
}

 

你可能感兴趣的:(Spring)