Spring之基于xml的自动装配、基于Autowired注解的自动装配
创始人
2024-05-26 06:52:25
0

文章目录

      • 基于xml的自动装配
        • ①注解
        • ②扫描
        • ③新建Maven Module
        • ④创建Spring配置文件
        • ⑤标识组件的常用注解
        • ⑥创建组件
        • ⑦扫描组件
        • ⑧测试
        • ⑨组件所对应的bean的id
      • 基于注解的自动装配
        • ①场景模拟
        • ②@Autowired注解
        • ③@Autowired注解其他细节
        • ④@Autowired工作流程
        • @Autowire 注解的原理
        • @Qualifier 注解的使用
        • NoSuchBeanDefinationException

基于xml的自动装配

①注解

和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

本质上:所有一切的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行。

②扫描

Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后续操作。

③新建Maven Module

org.springframeworkspring-context5.3.1junitjunit4.12test

④创建Spring配置文件

在这里插入图片描述

⑤标识组件的常用注解

@Component:将类标识为普通组件

@Controller:将类标识为控制层组件

@Service:将类标识为业务层组件

@Repository:将类标识为持久层组件

问:以上四个注解有什么关系和区别?
在这里插入图片描述

通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。

对于Spring使用IOC容器管理这些组件来说没有区别。所以@Controller、@Service、@Repository这三个注解只是给开发人员看的,让我们能够便于分辨组件的作用。

注意:虽然它们本质上一样,但是为了代码的可读性,为了程序结构严谨我们肯定不能随便胡乱标记。

⑥创建组件

创建控制层组件

@Controller
public class UserController {
}

创建接口UserService

public interface UserService {
}

创建业务层组件UserServiceImpl

@Service
public class UserServiceImpl implements UserService {
}

创建接口UserDao

public interface UserDao {
}

创建持久层组件UserDaoImpl

@Repository
public class UserDaoImpl implements UserDao {
}

⑦扫描组件

情况一:最基本的扫描方式



情况二:指定要排除的组件(用得多)






情况三:仅扫描指定组件



⑧测试

@Test
public void testAutowireByAnnotation(){ApplicationContext ac = newClassPathXmlApplicationContext("applicationContext.xml");UserController userController = ac.getBean(UserController.class);System.out.println(userController);UserService userService = ac.getBean(UserService.class);System.out.println(userService);UserDao userDao = ac.getBean(UserDao.class);System.out.println(userDao);
}

⑨组件所对应的bean的id

在我们使用XML方式管理bean的时候,每个bean都有一个唯一标识,便于在其他地方引用。现在使用注解后,每个组件仍然应该有一个唯一标识。

默认情况:

类名首字母小写就是bean的id。例如:UserController类对应的bean的id就是userController。

自定义bean的id:

可通过标识组件的注解的value属性设置自定义的bean的id

@Service(“userService”)//默认为userServiceImpl

public class UserServiceImpl implementsUserService {}

基于注解的自动装配

①场景模拟

参考基于xml的自动装配

在UserController中声明UserService对象

在UserServiceImpl中声明UserDao对象

②@Autowired注解

**在成员变量上直接标记@Autowired注解即可完成自动装配,不需要提供setXxx()方法。**以后我们在项目中的正式用法就是这样。

@Controller
public class UserController {@Autowiredprivate UserService userService;public void saveUser(){userService.saveUser();}
}
public interface UserService {void saveUser();
}
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Overridepublic void saveUser() {userDao.saveUser();}
}
public interface UserDao {void saveUser();
}	
@Repository
public class UserDaoImpl implements UserDao {@Overridepublic void saveUser() {System.out.println("保存成功");}
}

③@Autowired注解其他细节

@Autowired注解还可以标记在构造器和set方法上,完成自动装配

@Controller
public class UserController {private UserService userService;@Autowiredpublic UserController(UserService userService){this.userService = userService;}public void saveUser(){userService.saveUser();}
}
@Controller
public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService){this.userService = userService;}public void saveUser(){userService.saveUser();}
}

④@Autowired工作流程

在这里插入图片描述

@Autowire 注解的原理

a) 默认通过 byType 的方式,在IOC容器中通过类型匹配某个bean为属性赋值,如果不存在类型匹配的话直接报NoSuchBeanDefinationException

b) 当有多个 bean 的类型能匹配到,其会转换为 byName 的方式,根据@Autowired标记位置成员变量的变量名作为bean的id进行匹配。

c) byType和byName都失效的时候,即byType有多个 bean 的类型能匹配到,但byName和其中任何一个类型相同的比较id都不一样,则报 noUniqueBeanDefinationException.

d) 要解决c),可以使用@Qualifier注解:根据@Qualifier注解中指定的名称作为bean的id进行匹配

当执行:

@Test
public void test3(){ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");UserController userController = ioc.getBean(UserController.class);userController.saveUser();
}

其中userService成员变量进行扫描的时候

@Autowired
private UserService userService;

会找到两个bean,类别都为UserService,同时默认byName要找的是userService,配置的bean的id却为userServiceAAA,也不等于userService,因此报错:



@Qualifier 注解的使用

我们可以在指定的地方使用下面的注解,强行指定要匹配的id:

package com.jxz.spring.controller;import com.jxz.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;@Controller("jxzController")
public class UserController {@Autowired@Qualifier("userServiceAAA")private UserService userService;public void saveUser(){userService.saveUser();}
}

NoSuchBeanDefinationException

当匹配不到相同类型的Bean完成自动装配的时候,会报 NoSuchBeanDefinationException 的错误,这是因为@Autowire(required = true),必须完成自动装配,不然直接报错。

当修改为 @Autowire(required = false) 的时候,表示不是必须自动状态,找不到Bean则使用默认值,和之前使用XML自动装配的时候的情况一样。

比如:将依赖的UserDaoImpl注释掉,报NoSuchBeanDefinationException

package com.jxz.spring.dao.impl;import com.jxz.spring.dao.UserDao;
import org.springframework.stereotype.Repository;//@Repository
public class UserDaoImpl implements UserDao {@Overridepublic void saveUser() {System.out.println("保存成功");}
}

在对应的调用方修改:

@Service
public class UserServiceImpl implements UserService {@Autowired(required = false)private UserDao userDao;public void saveUser(){userDao.saveUser();}
}

因为要用到private UserDao userDao,但是却不能完成自动装配,因此使用默认值null,于是 userDao.saveUser();报java.lang.NullPointerException

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...