前言
刚学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.dao、com.hg.service、com.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面试的高频考点,记住这几个核心差异,面试不翻车:
-
来源不同:@Autowired是Spring官方提供的专属注解;@Resource是Java EE的规范注解,来自JSR-250标准。
-
注入规则不同:@Autowired默认按类型注入,必须配合@Qualifier才能实现按名称注入;@Resource默认按名称注入,名称匹配不到才会降级按类型注入。
-
兼容性不同:@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文件。
今天我们完整讲了:
-
注解开发的前置配置:包扫描的配置方式和核心作用;
-
注册Bean的四大注解:@Component全家桶的用法、区别和最佳实践;
-
依赖注入的三大注解:@Autowired、@Resource、@Value的用法和坑点;
-
注解开发新手最容易踩的5个坑,帮大家提前避坑。
现在的企业级开发,不管是传统SSM还是SpringBoot、SpringCloud,基本都是全注解开发,掌握这些注解,是Java开发的必备基本功。