Springboot基础篇(3):Bean管理

前言:Spring 通过扫描类路径(Classpath)来查找带有特定注解(如 @Component、@Service、@Repository 等)的类,并将它们注册为 Spring 容器中的 Bean。

1 Bean扫描

  1. Bean 扫描是 Spring 框架的核心功能之一,通过注解和配置可以灵活控制 Bean 的注册和扫描范围
  2. Bean的扫描范围:Spring Boot 默认会扫描主应用程序类(即带有 @SpringBootApplication 注解的类)所在包及其子包中的所有组件【原因在第四点】
  3. 自定义扫描范围:使用 @ComponentScan 注解指定要扫描的包路径。
java 复制代码
@SpringBootApplication
@ComponentScan(basePackages = {"com.example", "com.anotherpackage"})
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
  1. @SpringBootApplication 是一个组合注解,包含以下三个核心注解:
    @SpringBootConfiguration:标记该类为 Spring Boot 的配置类。
    @EnableAutoConfiguration:启用 Spring Boot 的自动配置功能。
    @ComponentScan: 启用组件扫描功能,默认扫描主应用程序类所在的包及其子包。

2 Bean注册

2.1 概念

Bean 注册是指将 Java 对象交给 Spring 容器管理,使其成为 Spring Bean 的过程

2.2 注册方式

  1. 基于注解的注册
java 复制代码
/*
用于标注普通组件类。
Spring 会自动扫描并注册该类为 Bean
*/
@Component
public class MyComponent {
    // 组件逻辑
}
/*
用于标注服务层组件。
是 @Component 的特化形式,语义上更明确
*/
@Service
public class MyService {
    // 服务逻辑
}
/*
很少用
用于标注数据访问层(DAO)组件。
是 @Component 的特化形式,支持异常转换
*/
@Repository
public class MyRepository {
    // 数据访问逻辑
}
/*
用于标注控制器层组件(如 Spring MVC 控制器)。
是 @Component 的特化形式。
*/
@Controller
public class MyController {
    // 控制器逻辑
}
  1. 基于 XML 的 Bean 注册:在早期的 Spring 版本中,Bean 通常通过 XML 配置文件注册。虽然现在推荐使用注解,但 XML 配置仍然支持
xml 复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 注册一个 Bean -->
    <bean id="myService" class="com.example.MyService"/>
</beans>
  1. 基于 Java 配置的 Bean 注册:如果要注册的bean对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明bean的,此时需要在配置类中进行注册

CommonConfig.java

java 复制代码
@Configuration// 配置注解
public class CommonConfig {
    /**
     * @Bean注解标注的方法会被 Spring容器调用,并将返回值注册为一个 Bean
     */
    @Bean
    public Country country(){
        return new Country();
    }
     /**
     * 默认情况下,Bean 的名称是方法名。你可以通过name或value属性指定Bean的名称。
     */
    @Bean(name = "customService")
    public MyService myService() {
        //Bean 的名称为 customService,而不是默认的 myService。
        return new MyService();
    }
}

SpringbootBeanRegisterApplication.java

java 复制代码
/*
1@Import 是 Spring 框架中的一个注解,用于将其他配置类或组件类导入到当前配置类中
2@Import 可以标注在 @Configuration 类或 @Component 类上,用于导入其他配置类或组件类
3@Import 可以同时导入多个配置类。
4@Import 还可以导入实现了 ImportSelector 接口的类,用于动态选择需要导入的配置类或组件类
*/
@Import(com.wfs.config.CommonImportSeletor.class)//使用@Import导入ImportSelector
//@Import(com.wfs.config.CommonConfig.class)
@SpringBootApplication
public class SpringbootBeanRegisterApplication {
    public static void main(String[] args) {
      ApplicationContext context =  SpringApplication.run(SpringbootBeanRegisterApplication.class, args);//获取ioc容器
      Country country = context.getBean(Country.class);//获取bean
      System.out.println(country);
      System.out.println(context.getBean("aa"));
    }

CommonImportSeletor.java

java 复制代码
package com.wfs.config;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @ImportSelector:导入选择器
 * 作用:导入指定配置类
 */
public class CommonImportSeletor implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.wfs.config.CommonConfig"};
    }
}
  1. 条件化的 Bean 注册:可以结合条件注解(如 @ConditionalOnProperty、@ConditionalOnClass 等)实现条件化的 Bean 注册
java 复制代码
@Configuration
public class CommonConfig {
    /**
     * 1 Bean对象的名字默认是方法名
     * 2 @Bean("aa")自定义对象名
     * 3 方法注入:Spring会自动将容器中的 Bean 注入到方法的参数中。
     * 4 使用@ConditionalOnProperty 条件注入:配置文件中前缀是province,属性名为name的值若是wfs,则声明此Bean
     * 5 @ConditionalOnMissingBean 当不存在当前类型的bean时,才声明该bean
     * 6 @ConditionalOnClass 当classpath下存在指定类时,才声明该bean
     * @return
     */
    @Bean("aa")
    @ConditionalOnProperty(prefix = "province",name = "name" ,havingValue = "wfs")
    @ConditionalOnMissingBean
    @ConditionalOnClass(name = "com.wfs.config.CommonConfig")
    public Province province(@Value("${province.name}") String name,
                             @Value("${province.direction}") String direction) {
        Province province = new Province();
        province.setName(name);
        province.setDirection(direction);
        return province;
    }
}

3 Bean的依赖注入

  1. 构造器注入:推荐的方式,适用于强制依赖。
java 复制代码
@Service
public class MyService {
    private final MyRepository repository;
    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }
}
  1. Setter 注入:适用于可选依赖
java 复制代码
@Service
public class MyService {
    private MyRepository repository;
    @Autowired
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
}
  1. 字段注入:不推荐,因为不利于测试和代码可读性。
java 复制代码
@Service
public class MyService {
    @Autowired
    private MyRepository repository;
}
相关推荐
八股文领域大手子2 小时前
JVM垃圾回收器深度底层原理分析与知识体系构建
java·jvm·算法
虾球xz2 小时前
游戏引擎学习第124天
java·学习·游戏引擎
码熔burning3 小时前
(十)趣学设计模式 之 外观模式!
java·设计模式·外观模式
一小路一3 小时前
从0-1学习Mysql第五章: 索引与优化
数据库·后端·学习·mysql·面试
mah6663 小时前
SpringBoot项目连接Oracle视图报错整理
spring boot·后端·oracle
计算机毕设定制辅导-无忧学长3 小时前
Maven 生命周期与构建命令(一)
java·maven
老朋友此林3 小时前
浅析 Redis 分片集群 Cluster 原理、手动搭建、动态伸缩集群、故障转移
java·数据库·redis
CodeCaster3 小时前
他来了,为大模型量身定制的响应式编程范式(1) —— 从接入 DeepSeek 开始吧
java·ai·langchain
IT学长编程4 小时前
计算机毕业设计 基于SpringBoot的智慧社区管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·后端·毕业设计·课程设计·论文笔记·1024程序员节
hadage2334 小时前
--- spring MVC ---
java·spring·mvc