『深入学习 Spring Boot』(六) 配置 Spring Bean 的 N 种姿势

324 阅读2分钟

前言

前段事件分别学习了,系统初始化器、监听器。从现在开始进入到核心中的核心 -- Bean 相关内容。

本部分核心内容就是探究,Bean 是如何被加载到 Spring Ioc 容器中的。

本小节,是 Bean 解析的第一小节,我们先来学习一下,Bean 有哪几种注册方式。

配置 Bean 的 N 种姿势

最原始的当然是 Xml 配置的方式了,但是因为本系列核心在于 Spring Boot ,所以 Spring 时代 Xml 的配置方式就不过多介绍了。

注解 @Component

这是我们最常用的方式了。用在类上,将此类注入到 Spring Ioc 容器中。

这里的 @Component 指得是所有包含 @Component 的注解,例如 @Controller 、@Service等等。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    @AliasFor(annotation = Component.class)
    String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    @AliasFor(annotation = Component.class)
    String value() default "";
 
}

我们可以看到,@Controller 、@Service 这类注解,都是包含了 @Component 的。

注解 @Bean

这也是我们比较常用的方式。用在方法上,将方法返回值作为 Bean 注册。

以上两种,都是比较常用的方式,不做演示了。

实现 FactoryBean

  1. 抽象接口 MyBean

    public interface MyBean {
        String getName();
    }
    
  2. 实现类 MyOneBean

    public class MyOneBean implements MyBean{
        @Override
        public String getName() {
            return "MyOneBean";
        }
    }
    
  3. MyFactoryBean

    需要注意的是,这里也需要 @Component 加持。

    @Component
    public class MyFactoryBean implements FactoryBean<MyBean> {
        @Override
        public MyBean getObject() throws Exception {
            return new MyOneBean();
        }
        @Override
        public Class<?> getObjectType() {
            return MyBean.class;
        }
    }
    
  4. 测试

    @Test
    public void one() {
        System.out.println(myBean.getName());
    }
     
    // MyOneBean
    

实现 BeanDefinitionRegistryPostProcessor

  1. MyTwoBean

    public class MyTwoBean implements MyBean{
        @Override
        public String getName() {
            return "MyTwoBean";
        }
    }
    
  2. MyBeanDefinitionRegistryPostProcessor

    @Component
    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
            rootBeanDefinition.setBeanClass(MyTwoBean.class);
            beanDefinitionRegistry.registerBeanDefinition("myTwoBean",rootBeanDefinition);
        }
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        }
    }
    
  3. 测试

    @Testpublic void one() {    System.out.println(myBean.getName());} // MyTwoBean
    

实现 ImportBeanDefinitionRegistrar

  1. MyThreeBean

    public class MyThreeBean implements MyBean{    @Override    public String getName() {        return "myThreeBean";    }}
    
  2. MyImportBeanDefinitionRegistrar

    注意这个没有 @Component 注解

    public class MyImportBeanDefinitionRefistart implements ImportBeanDefinitionRegistrar {    @Override    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();        rootBeanDefinition.setBeanClass(MyThreeBean.class);        registry.registerBeanDefinition("myThreeBean",rootBeanDefinition);    }}
    
  3. 启动类上加 @Import(MyImportBeanDefinitionRefistart.class)

  4. 测试

    @Testpublic void one() {    System.out.println(myBean.getName());}// myThreeBean
    

总结

本小节,了解了几种注册 Bean 的方式。

主要是为后面 Bean 加载内容做铺垫。