Spring Framework是如何加载bean的

96 阅读4分钟

1. Spring框架是如何加载bean的?

Spring框架中,Bean的加载大致可以分为以下几个步骤:

  1. 配置文件解析:首先,Spring通过读取配置文件(可以是XML文件,也可以是使用基于注解的配置),来获取Bean的配置信息。

  2. BeanDefinition的注册:然后,Spring将每个Bean的配置信息封装为一个BeanDefinition对象,然后注册到BeanDefinitionRegistry中。BeanDefinition中包含了创建Bean的各种信息,如类名、是否是单例、依赖的Bean等。

  3. Bean的创建:在应用实际需要使用Bean的时候,Spring会从BeanDefinitionRegistry中取出BeanDefinition,然后通过反射或者工厂方法创建Bean的实例。

  4. 依赖注入:创建Bean实例之后,Spring会检查该Bean的依赖关系(包括构造器注入、Setter方法注入和字段注入),然后将依赖的Bean注入。

  5. 初始化:注入依赖之后,Spring会调用Bean的初始化方法。如果Bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet()方法;如果在配置中通过init-method属性指定了初始化方法,Spring会调用这个方法。

  6. Bean的使用:至此,Bean就创建并初始化完成,可以供应用程序使用了。

  7. 销毁:在容器关闭时,如果Bean实现了DisposableBean接口,Spring会调用其destroy()方法;如果在配置中通过destroy-method属性指定了销毁方法,Spring会调用这个方法。

以上是Spring框架加载Bean的大致过程。不同的版本和不同的配置方式可能会有一些差别,但是整体流程是相似的。

2. Spring在加载过程中bean有哪几种形态?

在Spring的Bean的生命周期中,Bean主要经历了以下几种形态:

  1. Bean定义(BeanDefinition):在Spring读取并解析配置文件或者注解后,会生成对应的BeanDefinition,这是Bean的第一个形态。BeanDefinition包含了所有的配置信息,例如Bean的类名,是否为单例,依赖的其他Bean等。它描述了如何创建一个Bean,但此时Bean的实例还未被创建。

  2. Bean实例化(Instantiation):当容器开始创建Bean时,首先会进行实例化操作,也就是调用Bean的构造函数创建一个新的Bean实例。

  3. Bean属性填充(Populate):实例化后,Spring将依据Bean的定义,通过依赖注入的方式将Bean的属性进行填充。

  4. Bean初始化(Initialization):属性填充完后,Spring会调用Bean的初始化方法。如果Bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet()方法。另外,如果配置中指定了init-method属性,Spring还会调用这个方法。

  5. Bean后处理(Post-Processing):在Bean初始化之后,Spring会进行后处理操作。这个步骤中,Spring容器允许BeanPostProcessor对Bean进行额外的处理,例如进行代理包装等。

  6. Bean准备就绪(Ready):经过上述步骤,Bean已经完全准备好,可以被应用程序使用了。

  7. Bean销毁(Destruction):在Spring容器关闭时,会销毁所有单例的Bean。如果Bean实现了DisposableBean接口,Spring会调用其destroy()方法。另外,如果配置中指定了destroy-method属性,Spring还会调用这个方法。

以上就是Spring在加载过程中Bean的主要形态。

3. 简单案例

下面的例子将使用Java配置,展示Spring如何加载并管理Bean。

首先,我们创建一个简单的Service接口和其实现类:

public interface MyService {
    String sayHello(String name);
}

@Service
public class MyServiceImpl implements MyService {
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

接下来,我们创建一个Java配置类,使用@ComponentScan来告诉Spring在哪里查找Bean:

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

然后,我们在主函数中创建一个Spring的ApplicationContext,通过它来获取和使用Bean:

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MyService myService = context.getBean(MyService.class);
        String message = myService.sayHello("World");
        System.out.println(message);  // 输出 "Hello, World"
    }
}

以上就是一个基础的Spring应用程序。当我们运行主函数时,Spring会做以下事情:

  1. 读取AppConfig配置类,然后扫描com.example包下的所有类。

  2. 找到MyServiceImpl类,发现它有@Service注解,所以把它作为一个Bean,生成对应的BeanDefinition。

  3. 当我们调用context.getBean(MyService.class)时,Spring首次创建MyServiceImpl的实例,填充其属性(本例中没有属性),然后调用初始化方法(本例中没有初始化方法)。

  4. 最后,我们得到了MyService的实例,并调用其sayHello方法。

这个例子仅展示了Spring最基础的部分。在实际的应用中,Spring还有很多高级的功能,例如AOP、事务管理、安全控制等。