组件注册方式:
@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
java
@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指定前缀);