目录
使用@Autowired+@Qualifier(value = "")
前面的博客中已经介绍了Spring的创建和使用第一版,第一版现在已经不怎么在使用了。下面将介绍目前Spring的常见用法。
Spring中想要更简单的存储和读取对象的核心方法是使用注解。
1.先创建出Spring项目出来
2.存储Bean对象
3.获取Bean对象
和1.0一样创建出一个Spring项目出来并在pom.xml文件中添加核心jar包,以及创建一个启动类:

在resources目录下面配置Spring.xml文件,Spring.xml文件中需要配置Spring组件的扫描路径:
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:content="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- https://www.springframework.org/schema/context/spring-context.xsd">
- //下面是配置文件的扫描路径,根据自己的文件所在的位置来处理这个路径
- <content:component-scan base-package="com.user">content:component-scan>
- beans>

上面是配置文件的扫描路径,根据自己的文件所在的位置来处理这个路径,像我在com.user.Controller目录下面创建了一个控制层文件UserController,那么我的扫描路径就可以写成com.user,这样设置以后Spring在扫描文件的时候,他就会去该目录下面查看。这里的写法不是唯一的,你也可以将路径写大一点,比如直接com也可以,但是不推荐。
给存储Bean对象添加注解
想要将对象存储在Spring中,就得给对象添加注解,二注解又分两种:类注解、方法注解
顾名思义就是在类的前面加上注解,像下面这样:
- @Controller
- public class UserController {
- public void Hi(String name){
- System.out.println("Hi:"+name);
- }
- }
类注解包括:@Controller(控制器存储)、@Service(服务存储)、@Repository(仓库存储)、@Component(组件存储)、@Configuration(配置存储)
首先我们的明白,我们再写一个Spring项目的时候,因为涉及到前后端的交互还有和数据库的交互。各个目录之间的层级关系一定要明确,关于层级关系,它相当于是编程规范,实行这种规范可以方便开发和维护代码,具体的东西还请自己去了解。
Controller处在控制层,主要负责前端数据的校验 ;
Service处在服务层,主要负责数据的处理还有组装;
Repository处在存储层,主要负责数据库中表的操作,以及将数据存储在数据库中;
Configuration处在配置层,主要负责管理系统的配置信息;
Component处在组件层,主要负责存放编写Spring项目所需要的公共组件。
它们之间的关系如下图:

其中
@Controller(控制器存储)、@Service(服务存储)、@Repository(仓库存储)、@Configuration(配置存储)都是@Component(组件存储)的子类

在方法的上面加上注解,方法注解必须配合类注解才能一起使用(因为Spring在扫描的时候是以类为单位来扫描的,如果类上面不加上注解,就扫描不到) :
- @Controller
- public class UserController {
- @Bean
- public User GoodBey(){
- User user = new User();
- user.setId(1);
- user.setName("韩梅梅");
- return user;
- }
- }
- public class User {
- private int Id;
- private String name;
-
- public void setId(int id) {
- Id = id;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "User{" +
- "Id=" + Id +
- ", name='" + name + '\'' +
- '}';
- }
- }
现在先来看一下它们的使用:


现在来详细讨论一下这两类注解:
方法注解目前包括:@Bean
在使用方法注解的时候要注意:方法注解必须配合类注解才能使用。
在我们写方法注解的时候,有时方法名可能很长,这时可以给Bean对象进行重命名操作,但是重命名以后就不能再使用方法名:
- @Bean(name = "GB")
- public User GoodBey(){
- User user = new User();
- user.setId(1);
- user.setName("韩梅梅");
- return user;
- }


关于Bean的命名
通常在使用注解的时候,要求在写类名的时候要采用大驼峰,而读取类名的时候要求类名的首字母要小写。如果类名中首个字母和第二个字母都是大写,那么在读取类名的时候就按照类名来读就可以了,这个时候不能在采用类名首字母小写,否者会报错:


我们查看Spring里面的原码就知道原因了:
在IDEA中按查找类的快捷键ctrl+N,找到AnnotationBeanNameGenerator这个类:

然后查看这个方法:

从上面就可以解释为什么会报错了
获取Bean对象也叫对象注入,是把对象取出放到某个类中。
对象注入的实现有以下3种方式:
1.属性注入
2.Setter注入
3.构造方法注入
属性注入就是在属性上面添加@Autowired注解。将UserService类注入到UserController类中,像下面这样:
- @Service
- public class UserService {
- /*
- * 根据ID获取用户数据
- */
- public User findUserById(Integer id){
- User user = new User();
- if(id==1){
- user.setId(1);
- user.setName("张三");
- }else{
- user.setId(2);
- user.setName("李四");
- }
- return user;
- }
-
- public void Hi(String name){
- System.out.println("Hi:"+name);
- }
- }
- @Controller
- public class UserController {
- //1.属性注入,从Spring中获取一个对象,并注入到当前类
- @Autowired
- private UserService userService;
-
- public User findSuerById(Integer id){
- return userService.findUserById(id);
- }
-
-
- public void Hi(String name){
- System.out.println("Hi:"+name);
- }
- }
- public class App {
- public static void main(String[] args) {
- //1.获取到Spring的上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
- //2.加载类注解Bean对象
- UserController userController = context.getBean("userController", UserController.class);
- //3.使用它里面的方法
- System.out.println(userController.findSuerById(1));
- }
- }

通过获得setter方法,然后在set方法上面加上@Autowired,将UserService类注入到UserController类中,像下面这样:
- @Controller
- public class UserController2 {
- private UserService userService;
- //1.Setter注入
- @Autowired
- public void setUserService(UserService userService) {
- this.userService = userService;
- }
-
- public User findUserById(Integer id){
- return userService.findUserById(id);
- }
- }
- public class App {
- public static void main(String[] args) {
- //1.获取到Spring的上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
- //2.加载类注解Bean对象
- UserController2 controller2 = context.getBean("userController2", UserController2.class);
- //3.使用它里面的方法
- System.out.println(controller2.findUserById(1));
- }
- }

利用Setter注入方式的步骤:1.定义属性 、2.生成属性setter方法、3.给setter方法添加@Autowired注解
构造方法注入是在类的构造方法中注入,将UserService类注入到UserController类中,像下面这样:
- @Controller
- public class UserController3 {
- private UserService userService;
-
- @Autowired
- public UserController3(UserService userService) {
- this.userService = userService;
- }
-
- public User findUserById(Integer id){
- return userService.findUserById(id);
- }
- }
- public class App {
- public static void main(String[] args) {
- //1.获取到Spring的上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
- //2.加载类注解Bean对象
- UserController3 userController3 = context.getBean("userController3", UserController3.class);
- //3.使用它里面的方法
- System.out.println(userController3.findUserById(1));
- }
- }
注意:在使用构造方法注入的时候,如果类中只存在一个构造方法,那么可以省略这个构造方法上面的注解@Autowired,但是两个和两个以上的构造方法的时候@Autowired不能省略。
三种注解优缺点:
我们在使用依赖注入的时候,不光只有@Autowired一种方式,还有另一种方式@Resource
- @Component
- public class UserBean {
- @Bean(name = "GB1")
- public User GoodBey1(){
- User user = new User();
- user.setId(1);
- user.setName("韩梅梅");
- return user;
- }
- @Bean(name = "GB2")
- public User GoodBey2(){
- User user = new User();
- user.setId(2);
- user.setName("李华");
- return user;
- }
- }
- @Controller
- public class UserController4 {
- @Resource(name="GB1")
- private User user;
-
- public User findClient(){
- return user;
- }
- }
- public class App {
- public static void main(String[] args) {
- //1.获取到Spring的上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
- //2.加载类注解Bean对象
- UserController4 userController4 = context.getBean("userController4", UserController4.class);
- //3.使用它里面的方法
- System.out.println(userController4.findClient());
- }
- }

之前在1.0版本中,我们讨论过获取Bean的时候,对于多个对象的同一种类型的Bean获取会报错
比如像下面这样:
- @Component
- public class UserBean {
- @Bean(name = "GB1")
- public User GoodBey1(){
- User user = new User();
- user.setId(1);
- user.setName("韩梅梅");
- return user;
- }
- @Bean(name = "GB2")
- public User GoodBey2(){
- User user = new User();
- user.setId(2);
- user.setName("李华");
- return user;
- }
- }
- @Controller
- public class UserController5 {
- @Autowired
- private User user;
-
- public User findClient(){
- return user;
- }
- }
- import com.user.Controller.*;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class App {
- public static void main(String[] args) {
- //1.获取到Spring的上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
- //2.加载类注解Bean对象
- UserController5 userController5 = context.getBean("userController5", UserController5.class);
- //3.使用它里面的方法
- System.out.println(userController5.findClient());
- }
- }

在分析出现上述错误之前,我们的先明白一个事情,那就是@Autowired和@Resource两个注解获取Bean对象是通过两种方式来获取的:
1.通过类型来获取
context.getBean(UserController5.class)
2.通过名称来获取
context.getBean("userController5")
如果根据名称来获取,获取不到,那么这两个注解就会去根据类型来获取,如果都获取不到就会报错。
现在再来分析上面报错的原因,在UserBean类里面,有两个方法,这两个方法的类型都是User,其中一个方法名是GB1,另一个是GB2。而我们在UserController5类里面将User类通过属性注入的方式注入进来,但是我们取Bean的名称为user,@Autowired就会在com.user目录下面去找这个Bean对象,很明显是找不到的。然后@Autowired就会采用类型User的方式来找,在UserBean类里面他发现有两个User类型的Bean对象,这是它就不知道调用那一个了,所以就会报错。
通过上面的分析,我们就可以在UserController5类里面修改Bean的名称,比如改为GB1:
- @Controller
- public class UserController5 {
- @Autowired
- private User GB1;
-
- public User findClient(){
- return GB1;
- }
- }
但是如果现在不能修改Bean对象的名称,那就通过一下的方法来解决了:
这种方式在介绍@Resource就演示过了,所以不在演示。
- @Controller
- public class UserController5 {
- @Autowired
- @Qualifier(value = "GB1")
- private User user;
-
- public User findClient(){
- return user;
- }
- }