Springboot 组件注册 条件注解
组件注册方式:
@Configuration+@Bean
1、作用
@Bean 是 Spring 中手动注册 Bean 的核心注解,作用在方法上,告诉 Spring: 该方法的返回值会被 Spring 容器管理(成为 IoC 容器中的一个 Bean);
2、自定义bean作用名
Bean 的默认名称是方法名(比如你代码中方法名是 user01),但可以通过 @Bean("userhaha") 自定义 Bean 名称; 容器启动时(或首次获取 Bean 时),会执行该方法并将返回对象存入 IoC 容器,后续获取 Bean 时直接从容器取(单例)或重新执行方法(多例)
@Bean("userhaha") // 自定义Bean名称为userhaha,替代默认的user01 public User user01(){...}3、@Scope 用于指定 Bean 的作用域(生命周期范围),核心作用是控制 Spring 容器创建 Bean 实例的数量和时机。
| 作用域 | 说明 |
|---|---|
singleton | (默认)单实例:IoC 容器启动时创建 Bean(懒加载除外),全局仅一个实例 |
prototype | 多实例:每次从容器获取 Bean 时,都会重新执行@Bean方法创建新实例 |
request | Web 环境:每个 HTTP 请求创建一个新实例 |
session | Web 环境:每个 HTTP Session 创建一个新实例 |
举例:
1、创建一个UserConfig配置类(@Configuration),然后在其中定义bean( @Bean("userhaha"))
再指定为多实例 @Scope("prototype")
@Configuration public class UserConfig { @Bean("userhaha") @Scope("prototype") public User user01(){ var user=new User(); user.setId(1); user.setName("张三"); return user; } } 在启动类中测试bean"userhaha"是单例还是多例。
@SpringBootApplication @MapperScan("org.example.mybatisdemo.mapper") public class MybatisDemoApplication { public static void main(String[] args) { var ioc=SpringApplication.run(MybatisDemoApplication.class, args); /*for(String name:ioc.getBeanDefinitionNames()){ System.out.println(name); }*/ Object userHaha1=ioc.getBean("userhaha"); Object userHaha2=ioc.getBean("userhaha"); System.out.println(userHaha1==userHaha2); } }| 注解 / 配置 | 核心作用 | 实例数量 | 执行结果(你的代码) |
|---|---|---|---|
@Bean("userhaha") | 注册 Bean 并指定名称 | 取决于 @Scope | - |
@Scope("prototype") | 多实例作用域 | 每次 getBean 新实例 | userHaha1==userHaha2 → false |
| 默认(无 @Scope) | 单实例作用域(singleton) | 全局唯一实例 | userHaha1==userHaha2 → true |
@Component
上篇博客已介绍过。
@Import
1、作用
在 Spring 的开发场景中,我们通常使用 @Component、@Service 或 @Bean 来将类注册到 IoC 容器。但这些方式都有局限性:
@Component 系列:必须能修改目标类的源码(添加注解)。
@Bean 方法:需要在配置类中手写实例化代码,对于大量类或复杂构造函数显得繁琐。
@Import的出现正是为了解决以下痛点:
第三方类无源码:如 Druid 连接池中的
FastsqlException,你无法在其源码上加@Component。批量快速注册:需要一次性将多个工具类或配置类导入容器,而不想写一堆
@Bean方法。解耦配置:将组件的扫描与定义分离,实现模块化配置。
一句话定义:
@Import是 Spring 提供的一种“直通式”注册机制,它允许开发者直接将指定的 Class 对象“硬塞”进 IoC 容器,无需目标类配合,也无需手动编写工厂方法。
2、工作原理
当 Spring 容器启动并扫描到带有 @Import(XXX.class) 的配置类时,它会直接实例化 XXX 类(调用其默认构造函数),并将其作为 Bean 注册到容器中。
3、组件命名规则
这是 @Import 与普通 @Component 最大的区别之一:
默认名称:目标类的全限定名(Full Qualified Name)。
例如:导入 com.alibaba.druid.FastsqlException,其在容器中的 Bean ID 默认为 "com.alibaba.druid.FastsqlException"。
条件注解
@ConditionalOnXxx
@ConditionalOnClass:如果类路径中存在这个类,则触发指定⾏为
@ConditionalOnMissingClass:如果类路径中不存在这个类,则触发指定⾏为
@ConditionalOnBean:如果容器中存在这个Bean(组件),则触发指定⾏为
@ConditionalOnMissingBean:如果容器中不存在这个Bean(组件),则触发指定⾏为
@ConditionalOnBean(value=组件类型,name=组件名字):判断容器中是否有这个类型的组
件,并且名字是指定的值
场景: ● 如果存在 FastsqlException 这个类,给容器中放⼀个 Cat 组件,名cat01, ● 否则,就给容器中放⼀个 Dog 组件,名dog01 ● 如果系统中有 dog01 这个组件,就给容器中放⼀个 User组件,名zhangsan ● 否则,就放⼀个User,名叫lisi
@Configuration public class AppConfig { @ConditionalOnClass(name="com.alibaba.druid.FastsqlException") @Bean public Cat cat01(){ return new Cat(); } @ConditionalOnMissingClass("com.alibaba.druid.FastsqlException") @Bean public Dog dog01(){ return new Dog(); } } 启动类中: @SpringBootApplication @MapperScan("org.example.mybatisdemo.mapper") public class MybatisDemoApplication { public static void main(String[] args) { for (String s : ioc.getBeanNamesForType(Cat.class)) { System.out.println("cat:"+s); } for (String s : ioc.getBeanNamesForType(Dog.class)) { System.out.println("dog:"+s); } } }总结
1、本文首先介绍了springboot的组件注册:@Bean;@Component;@ImPort
1)介绍了bean的作用,自定义bean作用名的方式(默认是方法名)还分享了@Scope的作用(用于指定 Bean 的作用域;指明 Spring 容器创建 Bean 实例的数量和时机);介绍四种作用域(singleton(默认),prototype,request,session)及其说明。
2)还介绍了@Import的作用(向 IoC 容器注册组件,解决@Component和@Bean的局限);工作原理;组件命名规则(目标类的全限定名)
2、还列出了一些条件注解:(@ConditionalOnXxx,@ConditionalOnClass,@ConditionalOnMissingClass,@ConditionalOnBean等等)并举了一个例子来演示@ConditionalOnClass和@ConditionalOnMissingClass注册组件的使用。
3、并介绍了如何在配置文件中为一个java对象赋值(将其注册为bean,再使用@ConfigurationProperties指定前缀);
