Spring内部类实例化

524 阅读1分钟

先看一个简单的例子

public class Parent {
   class Child{

   }

   public static void main(String[] args) {
      AnnotationConfigApplicationContext
            context = new AnnotationConfigApplicationContext();
      context.register(Child.class);
      context.refresh();
      System.out.println(context.getBean(Child.class));
   }
}

image.png

上面的例子可以看到,实例化内部类失败

一个java对象 要想成为一个bean,必须要经过锻造,这个过程称之为bean的生命周期

其中有一个非常重要的步骤:推断构造方法

spring在实例化Child的时候,必定要先去get Parent,但是get不到,因为我们并没有实例化Parent,所以报错No qualifying bean of type 'com.spring.Parent'。

Child作为Parent的内部类,如果直接单纯的把Child注册给spring容器去实例化Child会失败;可以理解为Child是Parent的一个成员变量;

Parent没有注册给spring容器,站在spring角度而言就是没有Parent的对象,那么成员变量自然无法实例化;

原理是因为在实例化Child的时候,spring推断Child使用的构造方法会推断出来一个需要带Parent的构造方法

public Child(Parent parent){};

而且spring会使用这个构造方法去实例化Child,实例化Child的过程当中会去 getBean(Parent.class),故而失败;

解决方法:

1、把Child定义成为一个静态的内部类;这样就不需要Parent的对象就能实例化Child

2、给Child提供一个带Parent的构造方法,并且把Parent注册给spring容器

AbstractAutowireCapableBeanFactory

// 来推断一下这个类有哪些构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);