Spring中@Bean标注的方法是如何创建对象呢?

在这里插入图片描述
在这里插入图片描述

博主 默语带您 Go to New World.
个人主页—— 默语 的博客👦🏻
《java 面试题大全》
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨

Spring中@Bean标注的方法是如何创建对象呢?

摘要

在本文中,我们将深入探讨Spring框架中使用@Bean标注的方法是如何创建对象的。我们将通过分析源码和实际案例演示,揭示Spring是如何通过FactoryMethod机制实现Bean的创建和管理的。此外,我们还会详细研究了@Bean标注方法中的参数注入过程,包括对同类型Bean的决策过程和使用@Primary注解的情况。

引言

在Spring框架中,@Bean注解是定义bean的一种方式,但背后的实现原理很多开发者可能并不清楚。本文旨在揭示@Bean标注的方法是如何被Spring创建成Bean的,以及其中涉及的源码细节。

Spring中的@Bean标注

创建Bean的过程

在一个典型的Spring配置类中,使用@Bean标注的方法会被Spring容器识别为Bean的创建方法。通过分析源码,我们发现Spring会为这些方法生成一个FactoryMethod,并通过执行该方法来创建Bean对象。让我们通过一个简单的配置类来演示这个过程:

@Configuration
public class MyConfiguration {

    @Bean
    public Blue blue() {
        System.out.println("创建 Blue 对象");
        return new Blue();
    }

}

上述代码中,blue()方法被标注为@Bean,最终通过执行FactoryMethod来创建Blue对象。这一过程将在后续源码分析中展开讨论。


在一个典型的Spring配置类中,使用@Bean标注的方法会被Spring容器识别为Bean的创建方法。通过分析源码,我们发现Spring会为这些方法生成一个FactoryMethod,并通过执行该方法来创建Bean对象。让我们通过一个简单的配置类来演示这个过程:

@Configuration
public class AppConfig {

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

在这个例子中,myBean方法使用了@Bean注解,告诉Spring容器需要调用这个方法来创建一个Bean对象。接下来,让我们通过源码分析一下Spring是如何处理这个配置类的。

  1. @Configuration注解的处理: 首先,Spring会检测到AppConfig类上标注了@Configuration注解,表示这是一个配置类,Spring会为该类创建一个CGLIB代理。这个代理类将用于拦截@Bean方法的调用,以便进行一些额外的处理。
  2. 处理@Bean方法: 当应用程序上下文启动时,Spring容器会扫描配置类,找到所有标注了@Bean的方法。对于每个@Bean方法,Spring会生成一个MethodInterceptor,该拦截器负责处理@Bean方法的调用。这个拦截器将被注册到CGLIB代理中。
  3. FactoryMethod的生成: 当应用程序需要获取MyBean时,实际上是通过调用CGLIB代理的myBean方法。该方法的执行会触发拦截器,拦截器会调用原始的myBean方法,并将其返回的对象作为Bean。
  4. Bean的生命周期管理: 如果MyBean类上有其他的生命周期注解(如@PostConstruct@PreDestroy),Spring容器会相应地处理这些生命周期方法。

总体来说,@Bean方法的执行过程经历了CGLIB代理、拦截器调用、原始方法执行等步骤,最终完成了Bean的创建和注入过程。这使得Spring框架能够实现很多高级特性,比如AOP(面向切面编程)和动态代理。

参数注入流程

在实际应用中,@Bean标注的方法可能包含参数,我们需要深入了解这些参数是如何被注入的。


在Spring中,@Bean标注的方法可以包含参数,而这些参数可以通过不同的方式进行注入。让我们深入了解这些参数注入的流程:

考虑以下的示例:

@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean(AnotherBean anotherBean) {
        return new MyBean(anotherBean);
    }
}

在这个例子中,myBean方法接受一个AnotherBean类型的参数。下面是参数注入的流程:

  1. 参数类型匹配: Spring容器会检查所有@Bean方法的参数,尝试查找与参数类型匹配的其他Bean。在这个例子中,Spring会查找容器中是否有一个类型为AnotherBean的Bean。
  2. Bean创建或注入: 如果找到了匹配的Bean,Spring容器将使用该Bean来满足myBean方法的参数。如果容器中没有匹配的Bean,通常会抛出异常,除非该参数允许为null,或者使用@Autowired(required = false)等方式处理。
  3. Bean的创建过程: 如果AnotherBean还没有被创建,那么Spring容器会按照相同的@Bean创建过程(参考前面的回答)来创建AnotherBean。这可能涉及到更多的方法拦截和CGLIB代理。
  4. 方法执行: 一旦所有的依赖关系都解析和注入完成,myBean方法将被调用,创建并返回MyBean实例。这个实例将包含通过参数传递进来的AnotherBean

总体来说,Spring使用参数类型匹配的方式来解析@Bean方法的参数,然后自动注入相应的Bean。这使得我们能够方便地在@Bean方法中引入其他组件或服务,并利用Spring容器来进行依赖注入。在复杂的应用中,还可以使用@Autowired@Qualifier等注解来更精确地控制注入过程。

根据参数名注入

如果@Bean方法存在参数,Spring容器会尝试根据参数名在容器中找到对应的Bean。如果成功找到,就将该Bean注入到方法中。


在Spring中,通过参数名进行注入是一种便捷的方式。如果@Bean方法存在参数,并且这些参数的名称与容器中的Bean定义的名称一致,Spring容器会尝试根据参数名自动注入相应的Bean。这种方式通常用于简化配置,避免手动指定@Qualifier@Autowired等注解。

考虑以下的示例:

@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean(AnotherBean anotherBean) {
        return new MyBean(anotherBean);
    }
}

在这个例子中,myBean方法有一个参数名为anotherBean,而且在容器中存在一个Bean定义的名称也为anotherBean。Spring容器会根据参数名自动将匹配的Bean注入到myBean方法中。

如果没有找到与参数名匹配的Bean,Spring容器通常会抛出异常,除非该参数允许为null,或者使用@Autowired(required = false)等方式处理。

这种根据参数名进行注入的方式适用于简单的情况,但在复杂的应用中,尤其是当存在多个相同类型的Bean时,可能需要使用更精确的方式,例如使用@Qualifier注解或者@Autowired结合构造函数来明确指定要注入的Bean。


  1. @Primary注解:
    • 如果有多个同类型的Bean,而且其中一个标注了@Primary注解,那么Spring容器会优先选择标注了@Primary注解的Bean进行注入。
@Component
@Primary
public class PrimaryBean implements MyInterface {
    // ...
}
  1. 实现@Comparator排序接口:
    • 如果没有@Primary注解,Spring容器将尝试比较这些Bean是否实现了Comparator接口。
    • 如果实现了,Spring容器会按照Comparator接口的排序规则选择排序结果的第一个Bean进行注入。
@Component
public class BeanA implements MyInterface, Comparator<BeanA> {
    // ...
}
  1. 根据入参名称和Bean的beanName进行比较:
    • 如果上述两个条件都不满足,Spring容器会尝试根据入参的名称和Bean的beanName进行比较。
    • 如果找到了与参数名或beanName匹配的Bean,就会将该Bean注入到目标位置。
    • 如果没有找到匹配的Bean,通常会抛出异常,除非该参数允许为null,或者使用@Autowired(required = false)等方式处理。
@Component("customBeanName")
public class BeanB implements MyInterface {
    // ...
}

总体来说,Spring容器会尽力按照上述规则选择合适的Bean进行注入。在实际应用中,合理使用@Primary注解、实现Comparator接口或者通过指定beanName等方式,可以更精确地控制同类型Bean的注入行为。


同类型Bean的决策过程

如果参数名未能匹配到Bean,Spring会根据参数类型在容器中查找匹配的Bean。但是,如果存在多个同类型的Bean,Spring会进行决策判断:

  • 首先,查看是否有Bean标注了@Primary注解,如果有,则使用该Bean进行注入。
  • 如果没有@Primary注解,Spring会判断这些Bean是否实现了@Comparator排序接口,如果有,将使用排序结果的第一个Bean进行注入。
  • 如果上述两个条件都不满足,Spring将尝试根据入参名称和Bean的beanName进行比较,匹配成功则注入该Bean,否则报错。

演示参数注入流程

让我们通过一个实际的配置类演示参数注入流程:

@Configuration
public class MyConfiguration {

    @Bean
    public Blue blue(White white1) {
        System.out.println("获取了 White 对象:" + white1);
        return new Blue();
    }

    @Bean
    @Primary
    public White white1() {
        White white = new White();
        System.out.println("创建的 White1 对象,携带 @Primary 注解:" + white);
        return white;
    }

    @Bean
    public White white2() {
        White white = new White();
        System.out.println("创建的 White2 对象:" + white);
        return white;
    }

}

上述代码展示了根据入参名称和@Primary注解进行参数注入的情况。我们将通过代码输出详细说明每一步的执行过程。

总结

通过本文的深入研究,我们对Spring框架中@Bean标注方法的创建过程和参数注入流程有了更清晰的认识。了解这些底层机制有助于我们更好地理解Spring容器的工作原理,提高在实际项目中使用Spring的技能。

参考资料

  1. Spring Framework Documentation
  2. Understanding the Spring @Bean Annotation
  3. Spring @Primary Annotation

希望通过本文的阐述,读者能更深入地了解Spring中@Bean标注方法的内部实现和参数注入机制。

文末赠书

在这里插入图片描述

内容介绍:

信息安全原理与实践》(第3版)经过全面修订和更新,新增了关于网络安全基础知识的章节,并扩展介绍了跨站脚本(XSS)攻击、Stuxnet和其他恶意软件、SSH协议、安全软件开发和安全协议。书中的新示例说明了RSA密码体系、椭圆曲线加密、SHA-3,以及包括比特币和区块链在内的散列函数的应用。更新后的习题、表和图有助于读者学习经典密码体系、现代对称加密、公钥加密、密码分析、简单认证协议、入侵和恶意软件检测系统、量子计算等实用知识。这本颇受欢迎的教科书涉及的信息安全方法非常实用:

l 涵盖快速发展的信息安全领域的最新内容。

l 解释会话密钥、完全正向保密、时间戳、SSH、SSL、IPSec、Kerberos、WEP、GSM和其他认证协议。

l 解决访问控制技术,包括认证和授权、ACL,以及多级安全和隔离项。

l 讨论软件安全问题,从恶意软件检测到安全软件开发。

l 包括教师解决方案手册、PowerPoint幻灯片、讲座视频和其他教学资源。

购买链接

🥇 赠书活动规则 📚

🌟 请关注我的博客,即刻获得更多珍贵的编程和考研资源。

📲 添加博主Wxx:我的微信号是Solitudemind,添加后即刻获得参与活动的资格。

💬 **活动参与方法:**在底部留言 "为梦想扬帆!加油!🚀

🎁 结果揭晓时间:在11月20日,我将从留言中随机抽取3名幸运读者,并将结果公布于评论区和微信朋友圈。

感谢大家的参与!🚀

🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

在这里插入图片描述

  • 24
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默 语

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值