ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Spring IoC 注解式开发完全指南

2026/10/1 2:48:59 拓冰建站 浏览量
Spring IoC 注解式开发完全指南 Spring IoC 注解式开发完全指南一、为什么需要注解式开发XML 配置时代一个稍微复杂的项目需要维护大量的 XML 文件。每新增一个 Bean就要在 XML 里加一段bean配置。依赖关系也全靠手动写property或constructor-arg配置量大、易出错、和代码分离导致阅读困难。注解式开发把配置信息直接写在 Java 类上代码和配置合一减少了 XML 的维护成本。Spring 从 2.5 开始支持注解到 3.0 之后逐步成为主流Spring Boot 更是完全基于注解。二、核心注解总览Spring IoC 注解分为两大类类别注解作用Bean 注册Component通用组件标记为 Spring BeanService业务层组件Repository数据访问层组件ControllerWeb 控制层组件Configuration配置类Bean方法级别注册返回值依赖注入Autowired按类型自动注入Qualifier配合Autowired按名称注入Primary同类型多 Bean 时指定首选Value注入简单类型和配置值ResourceJSR-250 标准按名称注入InjectJSR-330 标准按类型注入三、Bean 注册注解详解1. Component 及其派生注解Component是最基础的注解标记一个类为 Spring Bean。Service、Repository、Controller都是Component的派生注解语义更明确。ComponentpublicclassUserDao{publicvoidsave(){System.out.println(保存用户);}}ServicepublicclassUserService{publicvoidregister(){System.out.println(注册用户);}}为什么用Service而不是Component语义更清晰让代码的层次结构一目了然。Repository还额外提供了数据访问异常转换功能。Bean 的默认名称是类名首字母小写。也可以显式指定Service(userService)publicclassUserService{}2. Configuration BeanConfiguration标记一个类为配置类可以替代 XML 配置文件。Bean标记方法把方法返回值注册为 Bean。ConfigurationpublicclassAppConfig{BeanpublicDataSourcedataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/mydb);ds.setUsername(root);ds.setPassword(123456);returnds;}BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){returnnewJdbcTemplate(dataSource);}}Bean方法名默认就是 Bean 名称。方法参数会自动从容器中注入。Configuration类会被 CGLIB 代理保证Bean方法之间互相调用时返回的是容器中的单例。如果换成Component方法间调用会直接执行方法体创建新实例。3. ComponentScan告诉 Spring 扫描指定包下的组件ConfigurationComponentScan(com.example)publicclassAppConfig{}如果不指定包路径默认扫描当前类所在包及其子包。SpringBootApplication已经包含了ComponentScan。四、依赖注入注解详解1. Autowired按类型自动注入可以标注在字段、构造方法、Setter 方法上。字段注入ServicepublicclassUserService{AutowiredprivateUserDaouserDao;}构造器注入推荐ServicepublicclassUserService{privatefinalUserDaouserDao;AutowiredpublicUserService(UserDaouserDao){this.userDaouserDao;}}如果类只有一个构造方法Autowired可以省略。Setter 注入ServicepublicclassUserService{privateUserDaouserDao;AutowiredpublicvoidsetUserDao(UserDaouserDao){this.userDaouserDao;}}Autowired默认要求依赖必须存在找不到会抛NoSuchBeanDefinitionException。设置required false可以允许 nullAutowired(requiredfalse)privateUserDaouserDao;2. Qualifier当同一类型有多个 Bean 时用Qualifier指定名称ServicepublicclassOrderService{AutowiredQualifier(aliPayService)privatePaymentServicepaymentService;}也可以配合构造器参数publicOrderService(Qualifier(aliPayService)PaymentServicepaymentService){this.paymentServicepaymentService;}3. Primary同类型多 Bean 时标记其中一个为首选ServicePrimarypublicclassAliPayServiceimplementsPaymentService{}ServicepublicclassWechatPayServiceimplementsPaymentService{}ServicepublicclassOrderService{AutowiredprivatePaymentServicepaymentService;// 注入 AliPayService}Qualifier的优先级高于Primary。4. Value注入简单类型和配置值ComponentpublicclassAppConfig{Value(${app.name})privateStringappName;Value(${app.timeout:30})privateinttimeout;Value(${app.debug:false})privatebooleandebug;}5. ResourceJSR-250 标准注解默认按名称注入找不到再按类型ServicepublicclassUserService{Resource(nameuserDaoImpl)privateUserDaouserDao;}Resource和Autowired的区别Autowired默认按类型Resource默认按名称Autowired支持required falseResource不支持Autowired支持构造器注入Resource不支持五、注解式开发完整示例// 配置类ConfigurationComponentScan(com.example)publicclassAppConfig{BeanpublicDataSourcedataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/mydb);returnds;}}// 数据访问层RepositorypublicclassUserDao{AutowiredprivateJdbcTemplatejdbcTemplate;publicvoidsave(Useruser){jdbcTemplate.update(INSERT INTO user (name) VALUES (?),user.getName());}}// 业务层ServicepublicclassUserService{privatefinalUserDaouserDao;AutowiredpublicUserService(UserDaouserDao){this.userDaouserDao;}publicvoidregister(Useruser){userDao.save(user);}}// 启动publicclassMain{publicstaticvoidmain(String[]args){ApplicationContextcontextnewAnnotationConfigApplicationContext(AppConfig.class);UserServiceuserServicecontext.getBean(UserService.class);userService.register(newUser(张三));}}六、注解 vs XML对比维度注解XML配置位置代码内独立文件可读性类与配置合一直观配置集中但和代码分离修改成本需重新编译改 XML 即可无需编译适用场景业务类、Controller、Service第三方类、动态配置灵活性编译期确定运行时可替换现代趋势主流逐步淘汰选择建议自己写的类用注解第三方类无法修改源码用Bean方法或 XML。Spring Boot 项目中几乎全部使用注解。七、常见问题1. Autowired 注入失败检查类是否被 Spring 管理有Component等注解检查包是否在ComponentScan范围内同类型多 Bean 时用Qualifier指定2. Configuration 与 Component 的区别Configuration类会被 CGLIB 代理Bean方法间调用返回容器中的单例。Component不会被代理方法间调用直接执行方法体。3. 循环依赖构造器注入的循环依赖无法解决启动时报BeanCurrentlyInCreationException。字段注入的循环依赖可以通过三级缓存解决。最好通过重构消除循环依赖。4. 注解不生效常见原因是包扫描范围没覆盖到或者类没有被 Spring 管理。检查ComponentScan的路径和启动类所在的包。八、总结维度核心要点Bean 注册Component、Service、Repository、Controller、Bean依赖注入Autowired按类型、Qualifier按名称、Resource按名称配置类ConfigurationComponentScan注入方式构造器注入推荐 Setter 注入 字段注入优先级QualifierPrimary 按类型匹配选择建议自己的类用注解第三方类用Bean注解式开发让 Spring 配置从 XML 的繁琐中解放出来代码更简洁、可读性更高。理解每个注解的语义和使用场景是掌握 Spring IoC 的基础。