第二篇:告别XML臃肿配置!Spring注解式IOC/DI保姆级教程,从入门到真香

前言

刚学Spring的时候,是不是被一大堆XML配置搞疯了?写一个类就要加一个<bean>标签,依赖多了之后,XML文件动辄几百行,改个配置还要翻半天,维护起来简直是噩梦。

还好Spring早就提供了注解式开发的能力,从Spring 2.5开始支持注解驱动,到现在SpringBoot全注解开发已经成了行业主流,一行XML都不用写,就能玩转IOC和DI。

今天这篇文章,就带大家从零开始,搞定Spring基于注解的IOC和DI,从配置步骤、核心注解,到新手踩坑指南,全给你安排得明明白白,看完就能直接上手,告别XML配置的痛苦!

一、注解式IOC前置准备:一行配置,开启注解新世界

想要用Spring的注解,第一步必须告诉Spring:你要去哪个包里扫描注解。不然你加再多注解,Spring也看不到,根本不会生效!

1. 核心配置:开启包扫描

我们只需要在Spring的application.xml配置文件里,加上这一行配置:

复制代码
配置说明:
  • base-package:指定Spring要扫描的包路径,Spring会扫描这个包,以及它下面所有子包中的类,识别类上的注解。

  • 举个例子:你配置了base-package="com.hg",那么com.hg.daocom.hg.servicecom.hg.controller这些子包,都会被扫描到。

  • 新手踩坑点:90%的新手都踩过这个坑------包路径配错了,比如你的类在com.hg.service里,结果你配成了com.hg.dao,那注解肯定不生效!

2. 包扫描到底做了什么?

Spring启动的时候,会读取这个配置,遍历指定包下的所有class文件,识别出类上添加了IOC相关注解的类,自动把这些类注册成Bean,放到IOC容器里,再也不用我们一个个写<bean>标签了,简直不要太爽!

二、Bean注册四大注解:@Component全家桶,告别<bean>标签

开启包扫描之后,我们只需要在类上加上对应的注解,Spring就会自动把这个类注册成容器里的Bean,不用再写繁琐的XML配置了。

这四个注解,核心功能完全一致------都是把类交给Spring容器管理,只是语义不同,用来区分不同的架构层级,让我们的代码结构更清晰、可读性更高。

1. 四大注解详解

注解 适用场景 核心说明
@Repository Dao层(数据访问层) 标注在数据访问层的实现类上,比如Mapper、Dao实现类
@Service Service层(业务逻辑层) 标注在业务逻辑层的实现类上,用于处理业务逻辑
@Controller Controller层(控制层) 标注在Spring MVC的控制器类上,用于处理前端请求
@Component 三层架构之外的通用组件 通用的组件注解,不属于上面三层的工具类、通用组件,都用这个

2. 代码示例,一看就会

(1)Dao层实现类,添加@Repository注解
复制代码
(2)Service层实现类,添加@Service注解
复制代码

3. 自定义Bean的名称

默认情况下,Spring给Bean生成的名称是类名首字母小写,比如UserServiceImpl对应的beanName是userServiceImpl。

如果你想自定义Bean的名称,直接在注解里指定即可:

复制代码

这样,我们通过getBean("userService"),就能精准拿到这个对象了。

4. 配合@Scope指定Bean的作用域

之前我们讲过Bean的5大作用域,用注解开发的时候,直接用@Scope注解就能指定,无需在XML里配置scope属性。

示例:

复制代码

@Scope里的取值,和XML里的scope属性完全一致,singleton、prototype、request、session、application都可直接使用。

三、依赖注入DI三大注解:告别set方法,一行注解搞定注入

Bean注册到容器里了,那依赖怎么注入呢?比如Service层要注入Dao层的对象,以前我们要在XML里写property属性,还要手写set方法,现在用注解,一行代码就搞定了!

Spring提供了3个核心的DI注解,分别应对不同的注入场景,我们一个个讲透。

1. @Autowired:按类型注入(最常用)

这是我们日常开发中用得最多的注入注解,核心特性是默认按Bean的类型进行依赖注入

用法示例:
复制代码
核心说明:
  • 只要容器里有唯一一个对应类型的Bean,就能自动注入成功,连set方法都不用写,超级方便。

  • 踩坑解决方案:如果容器里有多个同一个类型的Bean,@Autowired会直接报错,因为它不知道该注入哪一个。这时候配合@Qualifier注解,按名称指定要注入的Bean即可:

    复制代码

2. @Resource:按名称注入,也能按类型

这个注解不是Spring提供的,而是JSR-250规范里的官方注解,Spring做了完美支持。它的核心特性是默认按Bean的名称注入,找不到对应名称时,会自动降级按类型注入。

用法示例:
复制代码
面试常问:@Autowired和@Resource的核心区别

这个也是Java面试的高频考点,记住这几个核心差异,面试不翻车:

  1. 来源不同:@Autowired是Spring官方提供的专属注解;@Resource是Java EE的规范注解,来自JSR-250标准。

  2. 注入规则不同:@Autowired默认按类型注入,必须配合@Qualifier才能实现按名称注入;@Resource默认按名称注入,名称匹配不到才会降级按类型注入。

  3. 兼容性不同:@Autowired只有Spring框架支持;@Resource是Java标准规范,所有兼容JSR-250的框架都能支持。

3. @Value:注入基本类型和String

上面两个注解,都是用来注入容器里的Bean对象的,那我们要注入基本数据类型、String类型,甚至配置文件里的配置值,怎么办?用@Value注解就对了!

用法示例:
复制代码

@Value注解非常灵活,不仅能注入固定值,还能读取配置文件、环境变量、系统属性里的内容,日常开发中使用频率极高。

四、注解开发新手必踩的5个坑,避坑指南!

很多同学刚用注解的时候,会遇到各种"注解不生效"、"注入失败报空指针"的问题,90%都是踩了下面这些坑,今天给大家全部列出来,帮大家提前避坑!

坑1:包扫描路径配错了

这是最常见的坑!你的类加了注解,但是Spring的包扫描路径没有包含这个类所在的包,Spring根本扫描不到,注解自然就不生效了。

解决办法:检查context:component-scan的base-package,确保包含了你所有加注解的类的包路径。

坑2:注解加在了接口上,而不是实现类上

很多新手会把@Service、@Repository加在接口上,比如:

复制代码

记住:Spring是给类创建实例、注册Bean的,注解必须加在实现类上,接口上加了等于白加!

坑3:@Autowired注入时,容器里没有对应类型的Bean

比如你要注入UserDao,但是UserDao的实现类没加@Repository注解,容器里根本没有这个类型的Bean,@Autowired就会直接报错。

解决办法:检查要注入的类,有没有添加对应的注解,有没有被Spring的包扫描覆盖到。

坑4:单例Bean注入多例Bean,多例直接失效

这个我们之前也提过,单例Bean只会在容器启动时创建一次,依赖注入也只会执行一次,就算你注入的是多例Bean,也只会注入一次,后续不会自动更新新的实例,导致多例完全失效。

解决办法:可以使用lookup-method注入,或者每次使用时直接从容器中getBean获取,不要直接注入。

坑5:@Autowired注入的对象报空指针异常

很多时候,你明明加了@Autowired,但是运行的时候对象是null,大概率是因为你自己new了这个类的对象,而不是从Spring容器里获取的。

比如你在代码里写了UserService userService = new UserServiceImpl();,这个对象是你自己new出来的,Spring根本管不着,里面的@Autowired自然不会生效,肯定是null。

解决办法:所有要用到的Bean,都从Spring容器里获取,绝对不要自己手动new受Spring管理的类!

总结

看完这篇文章,相信大家已经能感受到Spring注解式开发的香了。对比传统的XML配置,注解开发不仅代码量更少,可读性更高,维护起来也更方便,注解和业务代码放在一起,改起来也不用来回翻XML文件。

今天我们完整讲了:

  1. 注解开发的前置配置:包扫描的配置方式和核心作用;

  2. 注册Bean的四大注解:@Component全家桶的用法、区别和最佳实践;

  3. 依赖注入的三大注解:@Autowired、@Resource、@Value的用法和坑点;

  4. 注解开发新手最容易踩的5个坑,帮大家提前避坑。

现在的企业级开发,不管是传统SSM还是SpringBoot、SpringCloud,基本都是全注解开发,掌握这些注解,是Java开发的必备基本功。

相关推荐
t198751282 小时前
TOA定位算法MATLAB实现(二维三维场景)
开发语言·算法·matlab
梦想的旅途22 小时前
如何通过 QiWe API 实现企业微信主动发消息
开发语言·python
jllllyuz2 小时前
粒子群算法解决资源分配问题的MATLAB实现
开发语言·算法·matlab
凌晨一点的秃头猪2 小时前
Python文件操作
开发语言·python
运维 小白2 小时前
2. 部署mysql服务并监控mysql
数据库·mysql·adb
摇滚侠2 小时前
讲一讲 SpringMVC,线程变量 ThreadLocal 的使用
java·spring boot·intellij-idea
myloveasuka2 小时前
C++进阶:利用作用域解析运算符 :: 突破多态与变量隐藏
开发语言·c++
小哇6662 小时前
第2篇:Spring Boot + WebSocket + 消息队列STOMP协议(Rabbitmq) 架构原理
后端·websocket
聪明人2 小时前
macOS安装Redis
数据库·redis·macos