ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring 声明 Bean 的注解详解

Spring 声明 Bean 的注解详解 Spring 声明 Bean 的注解详解一、概述Spring 声明 Bean 的注解分为两大类类级别注解和方法级别注解。类级别注解标注在类上Spring 通过组件扫描自动注册方法级别注解标注在Configuration类的方法上手动注册返回值。类别注解标注位置注册方式类级别Component类组件扫描类级别Service类组件扫描类级别Repository类组件扫描类级别Controller类组件扫描类级别RestController类组件扫描类级别Configuration类组件扫描方法级别Bean方法配置类中手动注册二、Component基础组件注解Component是最基础的 Bean 声明注解其他类级别注解都是它的派生注解。ComponentpublicclassUserDao{publicvoidsave(){System.out.println(保存用户);}}Bean 名称规则默认是类名首字母小写如UserDao→userDao。可以显式指定名称Component(myUserDao)publicclassUserDao{}特点通用性最强适合不属于任何特定层次的组件是Service、Repository、Controller的元注解被ComponentScan扫描后注册为 Bean三、Service业务层组件Service是Component的派生注解语义上表示业务逻辑层。ServicepublicclassUserService{AutowiredprivateUserDaouserDao;publicvoidregister(Useruser){userDao.save(user);}}为什么用 Service 而不是 Component功能上完全等价但语义更清晰。在代码审查时看到Service就知道这是业务层组件看到Repository就知道这是数据访问层组件。这种语义分层让项目结构更清晰。四、Repository数据访问层组件Repository是Component的派生注解专门用于数据访问层。它有一个额外功能异常转换。RepositorypublicclassUserDaoImplimplementsUserDao{AutowiredprivateJdbcTemplatejdbcTemplate;Overridepublicvoidsave(Useruser){jdbcTemplate.update(INSERT INTO user (name) VALUES (?),user.getName());}}当Repository类抛出数据库异常时Spring 会自动将其转换为 Spring 的统一数据访问异常体系DataAccessException。这样上层代码不需要处理特定数据库厂商的异常类型切换数据库时业务代码不受影响。五、Controller 和 RestControllerController标记 Web 控制层组件RestController是Controller和ResponseBody的组合。ControllerpublicclassPageController{GetMapping(/index)publicStringindex(){returnindex;// 返回视图名渲染模板}}RestControllerpublicclassUserController{AutowiredprivateUserServiceuserService;GetMapping(/user/{id})publicUsergetUser(PathVariableLongid){returnuserService.getById(id);// 直接返回 JSON}}Controller返回视图名由视图解析器渲染页面。RestController返回的对象直接作为 HTTP 响应体输出适合前后端分离的 RESTful API。六、Configuration配置类Configuration标记一个类为配置类可以替代 XML 配置文件。它本身也是一个Component会被组件扫描注册。ConfigurationpublicclassAppConfig{BeanpublicDataSourcedataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/mydb);returnds;}}Configuration与Component的区别Configuration类会被 CGLIB 代理保证Bean方法之间互相调用时返回容器中的单例。Component不会被代理方法间调用直接执行方法体创建新实例。ConfigurationpublicclassAppConfig{BeanpublicUserDaouserDao(){returnnewUserDao();}BeanpublicUserServiceuserService(){// 由于 CGLIB 代理userDao() 返回的是容器中的单例returnnewUserService(userDao());}}七、Bean方法级别声明Bean标注在Configuration类的方法上把方法返回值注册为 Bean。ConfigurationpublicclassAppConfig{BeanpublicDataSourcedataSource(){returnnewHikariDataSource();}BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){returnnewJdbcTemplate(dataSource);}}适用场景第三方类无法添加Component注解时需要复杂初始化逻辑的对象需要根据条件动态创建 Bean 时Bean方法参数Spring 会自动从容器中注入匹配的 Bean。BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){// dataSource 自动从容器注入returnnewJdbcTemplate(dataSource);}Bean 名称默认是方法名可以通过name或value指定Bean(myDataSource)publicDataSourcedataSource(){...}初始化和销毁方法Bean(initMethodinit,destroyMethodcleanup)publicMyBeanmyBean(){returnnewMyBean();}八、ComponentScan组件扫描ComponentScan告诉 Spring 扫描哪些包下的组件。ConfigurationComponentScan(com.example)publicclassAppConfig{}常用属性属性作用basePackages指定扫描的包路径basePackageClasses指定类所在包为扫描根路径includeFilters包含过滤器excludeFilters排除过滤器ComponentScan(basePackagescom.example,excludeFiltersComponentScan.Filter(typeFilterType.ANNOTATION,classesService.class))SpringBootApplication已经包含了ComponentScan默认扫描启动类所在包及其子包。九、Import导入配置Import用于导入其他配置类或普通类被导入的类会注册为 Bean。ConfigurationImport({DatabaseConfig.class,RedisConfig.class})publicclassAppConfig{}Import支持三种类型普通配置类Configuration类ImportSelector实现类ImportBeanDefinitionRegistrar实现类十、条件化声明 BeanConditional根据条件决定是否注册 BeanConfigurationpublicclassAppConfig{BeanConditional(WindowsCondition.class)publicFileServicewindowsFileService(){returnnewWindowsFileService();}BeanConditional(LinuxCondition.class)publicFileServicelinuxFileService(){returnnewLinuxFileService();}}Spring Boot 的条件注解注解条件ConditionalOnClassclasspath 中存在指定类ConditionalOnMissingClassclasspath 中不存在指定类ConditionalOnBean容器中存在指定 BeanConditionalOnMissingBean容器中不存在指定 BeanConditionalOnProperty配置属性满足条件ConditionalOnWebApplication是 Web 应用BeanConditionalOnMissingBeanpublicObjectMapperobjectMapper(){returnnewObjectMapper();}ConditionalOnMissingBean常用于提供默认实现允许用户通过自定义 Bean 覆盖。十一、Profile环境化声明 Bean根据激活的 Profile 决定是否注册 BeanConfigurationProfile(dev)publicclassDevConfig{BeanpublicDataSourcedevDataSource(){// 开发环境数据源}}ConfigurationProfile(prod)publicclassProdConfig{BeanpublicDataSourceprodDataSource(){// 生产环境数据源}}也可以通过启动参数激活java-jarmyapp.jar--spring.profiles.activeprod十二、各注解对比总结注解标注位置语义特殊功能Component类通用组件无Service类业务层无语义清晰Repository类数据访问层异常转换Controller类Web 控制层视图解析RestController类REST 控制器直接返回 JSONConfiguration类配置类CGLIB 代理Bean方法手动注册灵活创建ComponentScan类组件扫描指定扫描范围Import类导入配置导入其他配置类Conditional类/方法条件注册按条件决定Profile类/方法环境注册按 Profile 决定十三、最佳实践按层选择注解Controller 层用Controller或RestControllerService 层用ServiceDao 层用Repository。语义清晰便于维护。第三方类用 Bean无法修改源码的第三方类通过ConfigurationBean注册。条件化 Bean 用 ConditionalOnMissingBean提供默认实现允许用户覆盖。多环境用 Profile不同环境的 Bean 分开配置避免运行时判断。组件扫描范围控制在合理范围启动类放在根包下避免扫描到不需要的包影响启动速度。十四、总结维度核心要点类级别注解Component、Service、Repository、Controller、RestController、Configuration方法级别注解Bean扫描注解ComponentScan导入注解Import条件注解Conditional、ConditionalOnXxx环境注解Profile选择原则自己的类用类级别注解第三方类用BeanSpring 声明 Bean 的注解体系围绕“类级别自动扫描”和“方法级别手动注册”两条线展开。Component及其派生注解负责前者Bean负责后者。配合ComponentScan、Import、Conditional、Profile可以灵活地控制 Bean 的注册范围和条件。理解这些注解的语义和适用场景是掌握 Spring IoC 注解式开发的基础。
返回列表