这样注入 SpringBoot 中的 Bean

上次写了一个 SpringBoot 的 Demo 后,发现它确实简单好用,但是写着写着又忍不住在代码里 new 对象了,到底是怎么回事?原来是搞不清楚如何才能把对象注入到 Spring 的容器中。今天这篇文章就分享几种将组件 Bean 注入的方法

通过注解 @Controller,@Service,@Repository,@Component

适用场景:用得非常广泛的一种方式,对于有明确含义的类,通常用这种方法来将组件注入到容器

比如,@Controller 我们会标注在控制器类上,@Service 会标注在逻辑处理类上,@Repository 会标注在数据库相关的实体类上,除了上述的几个含义明确的类之外,其他的用 @Component 来标注

使用这种方式要配合组件扫描注解 @ComponentScan 来指定要扫描的包,我们在 SpringBoot 中没有指定,是因为主应用的注解 @SpringBootApplication 已经进行了指定

通过注解 @Bean

适用场景:引用第三方包中的类时,我们无法通过第一种方法给它标注注解,则可以用这种方法来注入组件

使用时,先创建一个配置类,对该类标注 @Configuration (这个注解被 @Component 标注,所以也会自动注入到容器),然后创建方法,在方法上标注 @Bean,方法返回组件类型

@Configuration
public class BeanConfiguration {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

public class MyBean {
    public MyBean() {
        System.out.println("MyBean Load...");
    }
}

启动 SpringBoot 应用后会在控制台输出:MyBean Load…

表明组件被自动注入到容器中了

通过注解 @Import

该方式可以快速的将一个类注入到容器中,它有几种注入方法:

  1. 在其他 Spring 组件中(被第一种方法里的注解进行了标注的类)添加该注解,注解接受一个数组传值,因此可以同时指定多个要注入的类
@Configuration
@Import({A.class, B.class})
public class BeanConfiguration {

}

public class A {
  public A(){
    System.out.println("A loading");
  }
}

public class B {
    public B(){
    System.out.println("B loading");
  }
}
  1. @Import 中通过 ImportSelector 接口实现类,传递要注入的组件
    在 selectImports 方法返回值里提供要注入的全类名以完成注入
@Configuration
@Import({Blue.class, Red.class, MyImportSelector.class})
public class BeanConfiguration {

}

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.henrywoo.springbootapp.bean.C"};
    }
}
  1. @Import 中通过 ImportBeanDefinitionRegistrar 接口实现类,传递要注入的组件。在 registerBeanDefinitions 方法中通过参数 beanDefinitionRegistry 的方法 registerBeanDefinition 注册要注入的组件
@Configuration
@Import({Blue.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class BeanConfiguration {

}

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(E.class);
        beanDefinitionRegistry.registerBeanDefinition("e",rootBeanDefinition);
    }
}
通过接口 FactoryBean

实现该接口,并在 getObject 方法中返回要注入的组件

@Component
public class MyFactoryBean implements FactoryBean<Black> {

    public MyFactoryBean() {
        System.out.println("factory bean loading...");
    }

    @Override
    public Black getObject() throws Exception {
        System.out.println("getObject-------------");
        return new Black();
    }

    @Override
    public Class<?> getObjectType() {
        return Black.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

通过 isSingleton 方法来指定是否是一个单例,getObjectType 方法返回组件的类类型

使用这种方式时要注意,当启动 SpringBoot 应用后,并不会立即注入组件 Black,而只是将 MyFactoryBean 注入,只有当调用

AnnotationConfigApplicationContext.getBean() 获取组件 MyFactoryBean 时,才会注入 Black

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyFactoryBean.class);
context.refresh();

System.out.println("启动SpringBoot,调用 getBean 前");
Object myFactoryBean = context.getBean("myFactoryBean");
System.out.println("调用 getBean 后");

参考打印信息

factory bean loading...
启动 SpringBoot,调用 getBean 前
getObject-------------
Black loading...
调用 getBean 后
单例 or 多例

要说一下,上面的注入方法,默认情况下得到的组件都是单例,想得到多实例怎么做?

除了 FactoryBean 接口可以指定是否单例外,通过在 @Bean 标注的方法上增加一个注解 @Scope(“prototype”)即可,这样每次获取 bean 时,得到的就是一个新的实例

总结

以上,就是注入组件到容器中的方法,掌握了这些技能,再也不担心遇到组件注入的问题时只能通过 new 解决对象创建了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值