0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

将bean放入Spring容器中有哪些方式

我快闭嘴 来源:CSDN威廉希尔官方网站 社区 作者:三尺微命 一介书生 2022-09-19 15:25 次阅读


将bean放入Spring容器中有哪些方式?

我们知道平时在开发中使用Spring的时候,都是将对象交由Spring去管理,那么将一个对象加入到Spring容器中,有哪些方式呢,下面我就来总结一下

1、@Configuration + @Bean

这种方式其实,在上一篇文章已经介绍过了,也是我们最常用的一种方式,@Configuration用来声明一个配置类,然后使用 @Bean 注解,用于声明一个bean,将其加入到Spring容器中。

具体代码如下:

@Configuration
publicclassMyConfiguration{
@Bean
publicPersonperson(){
Personperson=newPerson();
person.setName("spring");
returnperson;
}
}

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

2、@Componet + @ComponentScan

这种方式也是我们用的比较多的方式,@Componet中文译为组件,放在类名上面,然后@ComponentScan放置在我们的配置类上,然后可以指定一个路径,进行扫描带有@Componet注解的bean,然后加至容器中。

具体代码如下:

@Component
publicclassPerson{
privateStringname;

publicStringgetName(){

returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
@Override
publicStringtoString(){
return"Person{"+
"name='"+name+'''+
'}';
}
}

@ComponentScan(basePackages="com.springboot.initbean.*")
publicclassDemo1{
publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Demo1.class);
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

结果输出:

Person{name='null'}

表示成功将Person放置在了IOC容器中。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

3、@Import注解导入

前两种方式,大家用的可能比较多,也是平时开发中必须要知道的,@Import注解用的可能不是特别多了,但是也是非常重要的,在进行Spring扩展时经常会用到,它经常搭配自定义注解进行使用,然后往容器中导入一个配置文件。

关于@Import注解,我会多介绍一点,它有四种使用方式。这是@Import注解的源码,表示只能放置在类上。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interfaceImport{

/**
*用于导入一个class文件
*{@linkConfiguration@Configuration},{@linkImportSelector},
*{@linkImportBeanDefinitionRegistrar},orregularcomponentclassestoimport.
*/
Class[]value();

}

3.1 @Import直接导入类

代码示例如下:

publicclassPerson{
privateStringname;

publicStringgetName(){

returnname;
}

publicvoidsetName(Stringname){
this.name=name;
}

@Override
publicStringtoString(){
return"Person{"+
"name='"+name+'''+
'}';
}
}
/**
*直接使用@Import导入person类,然后尝试从applicationContext中取,成功拿到
**/
@Import(Person.class)
publicclassDemo1{

publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Demo1.class);
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

上述代码直接使用@Import导入了一个类,然后自动的就被放置在IOC容器中了。

注意:我们的Person类上 就不需要任何的注解了,直接导入即可。

3.2 @Import + ImportSelector

其实在@Import注解的源码中,说的已经很清楚了,感兴趣的可以看下,我们实现一个ImportSelector的接口,然后实现其中的方法,进行导入。

代码如下:

@Import(MyImportSelector.class)
publicclassDemo1{

publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Demo1.class);
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

classMyImportSelectorimplementsImportSelector{
@Override
publicString[]selectImports(AnnotationMetadataimportingClassMetadata){
returnnewString[]{"com.springboot.pojo.Person"};
}
}

我自定义了一个 MyImportSelector 实现了 ImportSelector 接口,重写selectImports 方法,然后将我们要导入的类的全限定名写在里面即可,实现起来也是非常简单。

3.3 @Import + ImportBeanDefinitionRegistrar

这种方式也需要我们实现 ImportBeanDefinitionRegistrar 接口中的方法,具体代码如下:

@Import(MyImportBeanDefinitionRegistrar.class)
publicclassDemo1{

publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Demo1.class);
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

classMyImportBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar{

@Override
publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){
//构建一个beanDefinition,关于beanDefinition我后续会介绍,可以简单理解为bean的定义.
AbstractBeanDefinitionbeanDefinition=BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
//将beanDefinition注册到Ioc容器中.
registry.registerBeanDefinition("person",beanDefinition);
}
}

上述实现其实和Import的第二种方式差不多,都需要去实现接口,然后进行导入。接触到了一个新的概念,BeanDefinition,可以简单理解为bean的定义(bean的元数据),也是需要放在IOC容器中进行管理的,先有bean的元数据,applicationContext再根据bean的元数据去创建Bean。

3.4 @Import + DeferredImportSelector

这种方式也需要我们进行实现接口,其实它和@Import的第二种方式差不多,DeferredImportSelector 它是 ImportSelector 的子接口,所以实现的方法和第二种无异。只是Spring的处理方式不同,它和Spring Boot中的自动导入配置文件 延迟导入有关,非常重要。使用方式如下:

@Import(MyDeferredImportSelector.class)
publicclassDemo1{
publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Demo1.class);
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
classMyDeferredImportSelectorimplementsDeferredImportSelector{
@Override
publicString[]selectImports(AnnotationMetadataimportingClassMetadata){
//也是直接将Person的全限定名放进去
returnnewString[]{Person.class.getName()};
}
}

关于@Import注解的使用方式,大概就以上三种,当然它还可以搭配@Configuration注解使用,用于导入一个配置类。

4、使用FactoryBean接口

FactoryBean接口和BeanFactory千万不要弄混了,从名字其实可以大概的区分开,FactoryBean, 后缀为bean,那么它其实就是一个bean, BeanFactory,顾名思义 bean工厂,它是IOC容器的顶级接口,这俩接口都很重要。

代码示例:

@Configuration
publicclassDemo1{
@Bean
publicPersonFactoryBeanpersonFactoryBean(){
returnnewPersonFactoryBean();
}

publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext(Demo1.class);
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

classPersonFactoryBeanimplementsFactoryBean<Person>{

/**
*直接new出来Person进行返回.
*/
@Override
publicPersongetObject()throwsException{
returnnewPerson();
}
/**
*指定返回bean的类型.
*/
@Override
publicClassgetObjectType(){
returnPerson.class;
}
}

上述代码,我使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,注意,我没有向容器中注入 Person, 而是直接注入的 PersonFactoryBean 然后从容器中拿Person这个类型的bean,成功运行。

5、使用 BeanDefinitionRegistryPostProcessor

其实这种方式也是利用到了 BeanDefinitionRegistry,在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,大概意思就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。

具体代码如下:

publicclassDemo1{
publicstaticvoidmain(String[]args){
AnnotationConfigApplicationContextapplicationContext=newAnnotationConfigApplicationContext();
MyBeanDefinitionRegistryPostProcessorbeanDefinitionRegistryPostProcessor=newMyBeanDefinitionRegistryPostProcessor();
applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
applicationContext.refresh();
Personbean=applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

classMyBeanDefinitionRegistryPostProcessorimplementsBeanDefinitionRegistryPostProcessor{

@Override
publicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry)throwsBeansException{
AbstractBeanDefinitionbeanDefinition=BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
registry.registerBeanDefinition("person",beanDefinition);
}
@Override
publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{

}
}

上述代码中,我们手动向beanDefinitionRegistry中注册了person的BeanDefinition。最终成功将person加入到applicationContext中,上述的几种方式的具体原理,我后面会进行介绍。

小结

向spring容器中加入bean的几种方式:

  • @Configuration + @Bean
  • @ComponentScan + @Component
  • @Import 配合接口进行导入
  • 使用FactoryBean。
  • 实现BeanDefinitionRegistryPostProcessor进行后置处理。


审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    495

    浏览量

    22060
  • spring
    +关注

    关注

    0

    文章

    340

    浏览量

    14340

原文标题:将Bean放入Spring容器中的五种方式

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    java spring教程

    Spring核心概念介绍控制反转(IOC)依赖注入(DI)集合对象注入等Bean的管理BeanFactoryApplicationContextSpring 在web中的使用
    发表于 09-11 11:09

    什么是java spring

    中查找依赖,而是容器在对象初始化时不等对象请求就主动依赖传递给它。■ 面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing
    发表于 09-11 11:16

    spring实例

    ;suffix"><value></value></property></bean></beans>  接下来,要指明哪些请求交给spring的DispatcherServlet来处理,所以在
    发表于 09-11 11:22

    怎么阅读Spring源码

    注入)。如果其中有一个类container里没找到,则抛出异常,比如常见的spring无法找到该类定义,无法wire的异常。还有就是嵌套bean则用了一下递归,container会放到
    发表于 05-04 15:21

    Spring工作原理

    的依赖关系核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean二.AOP(Aspect-Oriented Programming): 面向方面编程1.代理的两种
    发表于 07-10 07:41

    Spring认证」Spring Hello World 项目示例

    。现在使用向导窗口您的项目命名为HelloSpring,如下所示 -成功创建项目后,您的项目资源管理器中将包含以下内容-第 2 步 - 添加所需的库第二步,让我们在项目中添加 Spring
    发表于 08-17 13:49

    Spring Boot嵌入式Web容器原理是什么

    Spring Boot嵌入式Web容器原理Spring Boot的目标是构建“非常容易创建、独立、产品级别的基于Spring的应用”。这些应用是“立即可运行的”。在这个过程中,完全没有
    发表于 12-16 07:57

    Spring应用 1 springXML配置说明

    Spring应用 1 springXML配置说明 隐式对Spring容器注册Process   context:annotation-config / 为了在spring开发过程中,为
    发表于 01-13 12:20 386次阅读

    解析加载及实例化Bean的顺序(零配置)

    作者丨低调的JVM 来自丨CSDN https://blog.csdn.net/qq_27529917/article/details/79329809 在使用Spring时,Bean之间会有些依赖
    的头像 发表于 08-04 16:08 1324次阅读

    Spring认证」Spring IoC 容器

    Spring 容器Spring 框架的核心容器创建对象,将它们连接到配置中,并管理它们从创建到成熟的生命周期。
    的头像 发表于 06-28 13:27 762次阅读
    「<b class='flag-5'>Spring</b>认证」<b class='flag-5'>Spring</b> IoC <b class='flag-5'>容器</b>

    SpringBean的生命周期是怎样的?

    销毁 3. 写在最后 Spring Bean 的生命周期,面试时非常容易问,这不,前段时间就有个读者去面试, 因为不会回答这个问题,一面都没有过。 如果只讲基础知识,感觉和网上大多数文章没有区别
    的头像 发表于 10-11 15:08 1385次阅读

    浅谈Spring事务底层原理

    开启Spring事务本质上就是增加了一个Advisor,但我们使用@EnableTransactionManagement注解来开启Spring事务是,该注解代理的功能就是向Spring容器
    的头像 发表于 12-06 09:56 692次阅读

    Spring中获取bean的八种方式

    适用于Spring框架的独立应用程序,须要程序通过配置文件初始化Spring
    的头像 发表于 12-08 10:10 1701次阅读

    Spring Dependency Inject与Bean Scops注解

    DependsOn`注解可以配置Spring IoC容器在初始化一个Bean之前,先初始化其他的Bean对象。下面是此注解使用示例代码:
    的头像 发表于 04-07 11:35 691次阅读
    <b class='flag-5'>Spring</b> Dependency Inject与<b class='flag-5'>Bean</b> Scops注解

    Spring容器原始Bean是如何创建的?Spring源码中方法的执行顺序

    这个话题其实非常庞大,我本来想从 getBean 方法讲起,但一想这样讲完估计很多小伙伴就懵了,所以我们还是一步一步来,今天我主要是想和小伙伴们讲讲 Spring 容器创建 Bean 最最核心的 createBeanInstan
    的头像 发表于 08-04 10:12 587次阅读
    <b class='flag-5'>Spring</b><b class='flag-5'>容器</b>原始<b class='flag-5'>Bean</b>是如何创建的?<b class='flag-5'>Spring</b>源码中方法的执行顺序