第三章、容器:IoC
1、是什么
1、是Inversion of Control的简写,译为“控制反转”,是一种设计思想,一个重要的面向对象编程法则
2、能知道我们如何设计松耦合,更牛的程序
3、Spring通过Ioc容器管理所有java对象的实例化和初始化,控制对象,和对象之间的依赖关系。
4、我们将由Ioc容器管理的java对象称为Spring Bean
5、它与使用关键字new创建的java对象没有任何区别
6、Ioc是Spring框架最重要的核心组件之一,贯穿Spring诞生和成长的过程
7、配置文件以XML、java注解或java代码实现
2、怎么用
1、理解

1、控制反转(Ioc)
1、是一种思想
2、降低程序的耦合度,提高程序扩展能力
1、反转什么?
1、将对象的创建权利交给第三方容器负责
2、对象和对象之间关系的维护权,交给第三方容器负责
2、如何实现?
1、DI(Dependency injection):依赖注入
2、容器使用的map集合(方便,key-value)
3、图解

2、依赖注入(DI)
1、 是什么?
1、DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想
2、指Spring创建对象的过程中,将对象依赖属性通过配置进行注入
2、怎么用(两种方式)
1、set注入
2、构造注入
3、总结
1、IOC是一种控制反转的思想,而依赖注入是对IoC的一种具体的实现
2、Bean管理:Bean对象的创建,以及Bean对象中属性的赋值(或叫Bean对象之间关系的维护)
3、IoC容器在Spring的实现(接口)
1、Spring的IoC容器就是IoC思想的产品,IoC容器中管理的组件也叫bean,在创建bean之前,首先需要创建IoC容器,Spring提供了IoC容器的两种实现方式
1、BeanFactory
1、是IoC容器的基本实现,面向Spring本身,不提供给开发人员使用
2、最基本的容器
2、ApplicationContext
1、是BeanFactory的子接口,提供更多的特性
2、面向Spring的使用者
3、几乎所有场合都使用ApplicaationContext,而不是底层的BeanFactory
BeanFactory。
③ApplicationContext的主要实现类
| 类型名 | 简介 |
|---|---|
| ClassPathXmlApplicationContext | 通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象 |
| FileSystemXmlApplicationContext | 通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象 |
| ConfigurableApplicationContext | ApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力。 |
| WebApplicationContext | 专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。 |

3、IOC、DI实现步骤
1、思路

1、编写配置文件
配置元数据,既是编写交给SpringIoC容器管理组件的信息,配置方式有三种。
1、基于 XML 的配置元数据的基本结构:
<bean id="..." [1] class="..." [2]>
<!-- collaborators and configuration for this bean go here -->
</bean>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 此处要添加一些约束,配置文件的标签并不是随意命名 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." [1] class="..." [2]>
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
2、\
-
id属性是标识单个 Bean 定义的字符串。 -
class属性定义 Bean 的类型并使用完全限定的类名。
2、实例化IOC容器
1、提供给 ApplicationContext 构造函数的位置路径是资源字符串地址,允许容器从各种外部资源(如本地文件系统、Java CLASSPATH 等)加载配置元数据。
2、例子(伪代码)
//实例化ioc容器,读取外部配置文件,最终会在容器内进行ioc和di动作
ApplicationContext context =
new ClassPathXmlApplicationContext("services.xml", "daos.xml");
3、获取Bean(组件)
1、ApplicationContext 是一个高级工厂的接口,能够维护不同 bean 及其依赖项的注册表。通过使用方法 T getBean(String name, Class requiredType) ,您可以检索 bean 的实例。
2、例子(伪代码)
//创建ioc容器对象,指定配置文件,ioc也开始实例组件对象
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
//获取ioc容器的组件对象
PetStoreService service = context.getBean("petStore", PetStoreService.class);
//使用组件对象
List<String> userList = service.getUsernameList();
4、基于XML管理Bean
1、搭建子模块Spring6-ioc-xml1
1、搭建模块
1、搭建方式如:Spring-first
2、引入配置文件
1、引入Spring-first模块配置文件:beans.xml、log4j2.xml
3、添加依赖
<dependencies>
<!--spring context依赖-->
<!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.2</version>
</dependency>
<!--junit5测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.1</version>
</dependency>
<!--log4j2的依赖-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.19.0</version>
</dependency>
</dependencies>
3、实验一:获取bean
1、前提创建User类、还有TestUser类
2、User类
package com.atqt.spring6_first_ico_xml1;
public class User {
private String name;
private Integer age;
public void run(){
System.out.println("run..........");
}
}
2、TestUser类
package com.atqt.spring6;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
// 创建Logger对象
private Logger logger = LoggerFactory.getLogger(TestUser.class);
@Test
public void testUserObjeect(){
// 加载spring的配置文件,对象创建
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
// 获取创建的对象
User user = (User) context.getBean("user");
// 使用对象调用方法进行测试
user.add();
// 手动写日志
logger.info("#################执行调用成功");
}
@Test
public void testUserObject1() throws Exception {
// 获取类的对象
Class clazz = Class.forName("com.atqt.spring6.User");
// 调用方法创建对象
User user = (User) clazz.getDeclaredConstructor().newInstance();
System.out.println(user);
}
}
3、bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 对象创建-->
<bean id="user" class="com.atqt.spring6_first_ico_xml1.User"></bean>
</beans>
1、方式一:获取id
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
// 根据id获取bean
User user1 = (User) context.getBean("user");
System.out.println("根据id获取bean"+user1);
2、方式二:根据类型获取
// 根据类型获取
User user2 = (User) context.getBean("user");
System.out.println("根据类型获取bean"+user2);
3、方式三:根据id和类型
// 根据id和类型获取bean
User user3 = (User) context.getBean("user", User.class);
System.out.println("根据id和类型获取bean"+user3);
4、注意
1、当根据类型获取bean时,要求IOC容器中指定类型的bean有且只有一个
2、如果bean配置了两个,而且根据类型获取bean的时候,就会报异常
3、异常原因是:只希望匹配1个单实例的bean对象,但是找到了2个
5、扩展
1、如果组件类实现了接口,根据接口类型可以获取bean吗
答案:可以,前提是bean唯一
2、如果一个接口有多个实现类,这些实现类都配置了bean,根据接口类型可以获取bean吗
答案:不可以,因为bean不唯一
6、结论
1、根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。
2、java中,instanceof运算符用于判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。也就是说:用instanceof关键字做判断时, instanceof
操作符的左右操作必须有继承或实现关系
3、实验二:IoC基于XML管理Bean依赖注入
1、创建一个类,给一个类中注入属性值
1、普通方法注入
1、就是创建一个类,定义两个私有属性
2、设置set方法,通过创建对象.set()进行值的赋予
3、也可以通过有参构造器,然后就可以在创建对象的时候,赋值
2、方法一:setter注入
1、先创建类,定义属性,设置get和set方法
package com.atqt.di;
public class Book {
private String bname;
private String author;
public Book() {
}
public Book(String bname, String author) {
this.bname = bname;
this.author = author;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
// 原生写法
public static void main(String[] args) {
Book book = new Book();
book.setBname("java");
book.setBname("尚硅谷");
}
// 构造器写法
Book book1 = new Book("java1","尚硅谷111");
}
2、在Spring中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 通过set方法注入-->
<bean id="book" class="com.atqt.spring.iocxm.di.Book">
<property name="bName" value="前端开发"></property>
<property name="author" value="尚硅谷"></property>
</bean>
</beans>
3、进行测试:编写测试类
package com.atqt.spring.iocxm.di;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBook {
@Test
public void testSetter(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);
}
}
4、实验三:依赖注入—构造器注入

1、传统方法注入
1、就是创建一个类的时候new xxx(参数1,参数2)
2、通过构造器
1、在Book类中添加有参构造器
// 有参构造器
public Book(String bName, String author) {
this.bName = bName;
this.author = author;
System.out.println("有参数执行了");
}
2、配置bean
<!-- 通过构造方法注入-->
<bean id="bookCon" class="com.atqt.spring.iocxm.di.Book">
<constructor-arg name="bName" value="java学习"></constructor-arg>
<constructor-arg name="author" value="尚硅谷"></constructor-arg>
</bean>
3、编写测试代码
@Test
public void testConst(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
Book book = context.getBean("bookCon", Book.class);
System.out.println(book);
}
5、实验四:特殊值处理
1、字面量赋值
1、字面量赋值
2、就和普通赋值一样
<constructor-arg name="author" value="尚硅谷"></constructor-arg>
2、null值
1、就是如何表示null值
2、在配置中设置
<!-- 通过set方法注入-->
<bean id="book" class="com.atqt.spring.iocxm.di.Book">
<property name="others">
<null></null>
</property>
</bean>
3、xml实体
1、就是在xml中的小括则号<不能随便写
2、使用xml实体代替
3、<:\<
4、>:\>
5、配置设置
<!-- 通过set方法注入-->
<bean id="book" class="com.atqt.spring.iocxm.di.Book">
<property name="others" value="<哈哈>"></property>
</bean>
4、CDATA节
1、是xml中的特有的
2、可以包含xml中的特殊符号
3、配置设置
<!-- 通过set方法注入-->
<bean id="book" class="com.atqt.spring.iocxm.di.Book">
<property name="others">
<value><![CDATA[a<bhhhhhh]]></value>
</property>
</bean>
6、实验五:为对象类型属性赋值
1、搭建前期环境
1、Emp类
package com.atqt.spring.iocxm.ditest;
public class Emp {
// 对象类型属性:员工属于某个部门
private Dept dept;
private String ename;
private Integer age;
public void work(){
System.out.println(ename+"empWork......"+age);
dept.info();
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2、Dept类
package com.atqt.spring.iocxm.ditest;
//部门
public class Dept {
private String dName;
public void info(){
System.out.println("部门输出.........."+dName);
}
public String getdName() {
return dName;
}
public void setdName(String dName) {
this.dName = dName;
}
}
2、方法一:外部bean引入
1、先用配置文件创建一个bean-ditest.xml 文件
2、创建两个类用bean标签创建
3、然后在一个新的bean中引入创建好的id=dept的bean标签,然后再根据id注入属性值(就相当于引入外部的bean)
4、个人理解:就相当于使用两个配置对象变量,然后使用ref标签调用类,从而达到外部引入的效果
4、格式
<bean id="xxxx" value="xxxx">
<bean id="yyyy" value="xxxx">
<.... ref="所需要引入的外部类">
其他该赋值赋值,该给定义属性就定义属性
5、代码实现
<!--
1、创建dep和emp类的对象
2、在emp的bean中,使用property引入dept的bean
-->
<bean id="dept" class="com.atqt.spring.iocxm.ditest.Dept">
<property name="dName" value="安保部"></property>
</bean>
<bean id="emp" class="com.atqt.spring.iocxm.ditest.Emp">
<!-- 最普通的属性注入-->
<property name="ename" value="lucy"></property>
<property name="age" value="50"></property>
<!-- 注入对象类型的属性-->
<property name="dept" ref="dept"></property>
</bean>
3、方法二:内部类引用
1、就是先用配置文件创建一个bean,bean中创建一个类对象A
2、在类对象A中的创建一个property标签
3、在这个property标签中创建一个bean标签,bean中创建一个对象B
4、这个就是内部类的引用
5、例子
<bean id="emp2" class="com.atqt.spring.iocxm.ditest.Emp">
<property name="ename" value="玛卡巴卡"></property>
<property name="age" value="55"></property>
<!-- 内部bean方式注入-->
<property name="dept">
<bean id="dept2" class="com.atqt.spring.iocxm.ditest.Dept">
<property name="dName" value="牛马部"></property>
</bean>
</property>
</bean>
4、方法三:级联属性赋值
1、就是创建两个bean,用bean创建两个对象
2、在对象A中的property中引入对象B,然后通过对象B.xxx属性来操作
3、代码实现
<!-- 第三种方式 级联赋值-->
<bean id="dept3" class="com.atqt.spring.iocxm.ditest.Dept">
<property name="dName" value="哈哈哈哈"></property>
</bean>
<bean id="emp3" class="com.atqt.spring.iocxm.ditest.Emp">
<property name="ename" value="神仙"></property>
<property name="age" value="30"></property>
<property name="dept" ref="dept3"></property>
<property name="dept.dName" value="哈哈哈哈2"></property>
</bean>
7、实验六:为数组类型属性赋值
1、环境
1、环境和实验五一样
2、需要在Emp类中添加一个数组类型变量loves
2、方法
1、格式
<!-- 注入数组类型-->
<property name="loves">
<array>
<value>数组属性值</value>
<value>数组属性值</value>
<value>数组属性值</value>
</array>
</property>
3、实现
1、bean配置文件实现
<!-- 注入数组类型属性-->
<bean id="dept" class="com.atqt.spring.iocxm.ditest.Dept">
<property name="dName" value="技术部"></property>
</bean>
<bean id="emp" class="com.atqt.spring.iocxm.ditest.Emp">
<!-- 注入普通的属性值-->
<property name="ename" value="lucy"></property>
<property name="age" value="20"></property>
<!-- 对象类型的属性-->
<property name="dept" ref="dept"></property>
<!-- 注入数组类型-->
<property name="loves">
<array>
<value>抽烟</value>
<value>唱歌</value>
<value>跳舞</value>
</array>
</property>
</bean>
8、实验七:为集合list类型属性赋值
1、环境
1、和实验六一样
2、需要多在Dept中添加一个list集合对象
private List<Emp> empList;
相应的get和set方法
3、在Dept类中info方法遍历一下集合,主要是方便实现
2、代码实现
<!-- 创建集合类型传入emp对象-->
<bean id="emp1" class="com.atqt.spring.iocxm.ditest.Emp">
<property name="ename" value="lucky1"></property>
<property name="age" value="20"></property>
</bean>
<bean id="emp2" class="com.atqt.spring.iocxm.ditest.Emp">
<property name="ename" value="lucky2"></property>
<property name="age" value="22"></property>
</bean>
<bean id="dept" class="com.atqt.spring.iocxm.ditest.Dept">
<property name="dName" value="技术部"></property>
<property name="empList">
<list>
<ref bean="emp1"></ref>
<ref bean="emp2"></ref>
</list>
</property>
</bean>
9、实验八:为Map类型数据赋值
1、环境
1、Student.java
package com.atqt.spring.iocxm.dimap;
import java.util.Map;
public class Student {
private String sId;
private String sName;
private Map<String ,Teacher> teacherMap ;
public Map<String, Teacher> getTeacherMap() {
return teacherMap;
}
public void setTeacherMap(Map<String, Teacher> teacherMap) {
this.teacherMap = teacherMap;
}
public void run(){
System.out.println("学生编号"+sId+"学生的姓名"+sName);
System.out.println(teacherMap);
}
public String getsId() {
return sId;
}
public void setsId(String sId) {
this.sId = sId;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
}
2、Teacher.java
package com.atqt.spring.iocxm.dimap;
public class Teacher {
private String tId;
private String tName;
public String gettId() {
return tId;
}
public void settId(String tId) {
this.tId = tId;
}
public String gettName() {
return tName;
}
public void settName(String tName) {
this.tName = tName;
}
@Override
public String toString() {
return "Teacher{" +
"tId='" + tId + '\'' +
", tName='" + tName + '\'' +
'}';
}
}
2、格式
<bean id="student" class="com.atqt.spring.iocxm.dimap.Student">
<property name="sId" value="100"></property>
<property name="sName" value="王五老师"></property>
<!-- 在学生bean中注入map集合类型属性-->
<property name="teacherMap">
<map>
<entry>
<key>
<!--key:的值-->
<value>101</value>
</key>
<!-- value:注入的对象-->
<ref bean="teacher1"></ref>
</entry>
</map>
</property>
</bean>
3、配置文件
1、bean-dimap.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="teacher1" class="com.atqt.spring.iocxm.dimap.Teacher">
<property name="tId" value="001"></property>
<property name="tName" value="张三老师"></property>
</bean>
<bean id="teacher2" class="com.atqt.spring.iocxm.dimap.Teacher">
<property name="tId" value="002"></property>
<property name="tName" value="张三老师"></property>
</bean>
<bean id="teacher3" class="com.atqt.spring.iocxm.dimap.Teacher">
<property name="tId" value="003"></property>
<property name="tName" value="李四老师"></property>
</bean>
<bean id="student" class="com.atqt.spring.iocxm.dimap.Student">
<property name="sId" value="100"></property>
<property name="sName" value="王五老师"></property>
<!-- 在学生bean中注入map集合类型属性-->
<property name="teacherMap">
<map>
<entry>
<key>
<value>101</value>
</key>
<ref bean="teacher1"></ref>
</entry>
<entry>
<key>
<value>102</value>
</key>
<ref bean="teacher2"></ref>
</entry>
<entry>
<key>
<value>103</value>
</key>
<ref bean="teacher3"></ref>
</entry>
</map>
</property>
</bean>
</beans>
2、测试代码
1、Test.java
package com.atqt.spring.iocxm.dimap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean-dimap.xml");
Student student = (Student) context.getBean("student");
student.run();
}
}
10、实验九:为引用集合类型在bean
1、环境
1、新加一个Lesson.java
package com.atqt.spring.iocxm.dimap;
public class Lesson {
private String lessonName;
public String getLessonName() {
return lessonName;
}
public void setLessonName(String lessonName) {
this.lessonName = lessonName;
}
@Override
public String toString() {
return "Lesson{" +
"lessonName='" + lessonName + '\'' +
'}';
}
}
2、在Student.java中添加一个List
private List<Lesson> lessonList;
2、配置文件
1、bean-diref.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="teacher10" class="com.atqt.spring.iocxm.dimap.Teacher">
<property name="tId" value="001"></property>
<property name="tName" value="张三老师"></property>
</bean>
<bean id="teacher11" class="com.atqt.spring.iocxm.dimap.Teacher">
<property name="tId" value="002"></property>
<property name="tName" value="李四"></property>
</bean>
<bean id="student" class="com.atqt.spring.iocxm.dimap.Student">
<property name="sId" value="张三"></property>
<property name="sName" value="李四"></property>
<!-- 注入list、map类型属性 -->
<property name="lessonList" ref="lessonList"></property>
<property name="teacherMap" ref="teacherMap"></property>
</bean>
<!-- 写这个变量的时候,需要注意xmlns的规范-->
<util:list id="lessonList">
<ref bean="lesson1"></ref>
<ref bean="lesson2"></ref>
<ref bean="lesson3"></ref>
</util:list>
<util:map id="teacherMap">
<entry>
<key>
<value>10000</value>
</key>
<ref bean="teacher10"></ref>
</entry>
<entry>
<key>
<value>10001</value>
</key>
<ref bean="teacher11"></ref>
</entry>
</util:map>
<bean id="lesson1" class="com.atqt.spring.iocxm.dimap.Lesson">
<property name="lessonName" value="java开发"></property>
</bean>
<bean id="lesson2" class="com.atqt.spring.iocxm.dimap.Lesson">
<property name="lessonName" value="python开发"></property>
</bean>
<bean id="lesson3" class="com.atqt.spring.iocxm.dimap.Lesson">
<property name="lessonName" value="测试测试"></property>
</bean>
</beans>
3、注意
1、这个util:map util:list 都是需要导入,命名空间
2、不然会出现报错问题
11、p命名空间
1、环境
1、和以上一样
2、注意:需要导入对应的命名空间格式
xmlns:p="http://www.springframework.org/schema/p"
2、配置文件
<bean id="studentp" class="com.atqt.spring.iocxm.dimap.Student"
p:sId="100" p:teacherMap-ref="teacherMap" >
</bean>
12、实验十:引入外部属性文件(以jdbc配置数据库为例)

1、作用
1、使用场景:jdbc的连接,需要引入外部的.properties文件
2、创建配置文件,引入context命名空间
3、引入属性文件,使用表达式完成注入
4、如果有内容需要修改,就不用修改上线所需的内容,
2、加入配置文件的依赖
1、pom.xml
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.15</version>
</dependency>
3、创建外部文件
1、jdbc.properties
jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver
4、引入属性文件
1、引入context名称空间
13、实验十一:bean的作用域
1、概念
1、配置bean标签的scope属性来制定bean的作用域范围
| 取值 | 含义 | 创建对象的时机 |
|---|---|---|
| singleton(默认) | 在IOC容器中,这个bean的对象始终为单实例 | IOC容器初始化时 |
| prototype | 这个bean在IOC容器中有多个实例 | 获取bean时 |
2、如果是在WebApplicationContext环境下还会有另外几个作用域(但不常用):
| 取值 | 含义 |
|---|---|
| request | 在一个请求范围内有效 |
| session | 在一个会话范围内有效 |
2、演示例子
1、创建以类User
package com.atqt.spring.iocxm.score;
public class User {
}
2、创建配置文件bean-scope.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 多实例的例子-->
<bean id="user" class="com.atqt.spring.iocxm.score.User" scope="prototype"></bean>
</beans>
3、进行测试类的创建和运行
package com.atqt.spring.iocxm.score;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestU {
@Test
public void demo1(){
// 多实例测试
ApplicationContext context = new ClassPathXmlApplicationContext("bean-scope.xml");
// 如果是scope="prototype",那就是多实例,singleton(默认)就是单实例
User user1 = context.getBean(User.class);
User user2 = context.getBean(User.class);
// 创建了2个对象呢
System.out.println(user1==user2);
}
}
14、实验十二:bean生命周期
1、具体的生命周期过程
1、bean对象的创建(调用无参构造器)
2、给bean对象设置属性(属性注入)
3、bean的后置处理器(初始化之前0
4、bean对象的初始化
5、bean后置处理器(初始化之后)
6、bean对象创建完成了,能够使用
7、bean对象销毁(配置指定的销毁方法)
8、IOC容器关闭了
2、补充标签
1、init-method:初始化标签
2、destroy-method:结束标签
#使用结束方法就需要创建实例化对象的类ClassPathXmlApplicationContext
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-life.xml");
context.close();
3、后置处理器
1、创建一个类,类继承BeanPostProcessor
2、重写接口中的两个方法
3、后置处理器,初始化之前的方法
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return xxxxx;
}
5、注意:bean创建接口的后置处理器,是针对IOC容器中的所有bean都会执行
6、后置处理器,初始化之后的方法
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return xxxx;
}
7、配置设置文件
#就是和为对象类型属性赋值的操作一样
15、实验十三:FactoryBean
1、简介
1、是spring提供的一种整合的第三方框架的常用机制
2、获取bean的时候得到的不是class属性中配置的这个类的对象,而是getObject()方法的返回值
3、可以把繁杂的细节机制屏蔽起来
4、将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqSessionFactory对象
2、例子
1、编写MyFactoryBean.java
package com.atqt.spring.iocxm.factorybean;
import com.atqt.spring.iocxm.score.User;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return null;
}
}
2、User.java
随便定义一些方法
3、配置文件设置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.atqt.spring.iocxm.factorybean.MyFactoryBean"></bean>
</beans>
16、实验十四:基于xml自动装配
1、理解
1、自动装配:根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类,类型或接口类型属性赋值

2、配置的两个概念
1、自动装配方式:byType
①根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值
②若在IOC中,没有任何一个兼容类型的bean能够为属性值赋值,则该属性不装配,因为默认值为null
③若IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException
2、自定装配方式:byName
①将自动装配的属性的属性名,作为bean的id在IONC容器中匹配相对应的bean进行赋值
3、例子
1、创建UserController.java
package com.atqt.spring.iocxm.auto.controller;
import com.atqt.spring.iocxm.auto.service.UserService;
import com.atqt.spring.iocxm.auto.service.UserServiceImpl;
public class UserController {
private UserService userService;
public void addUser(){
System.out.println("controller方法执行了");
UserService userService = new UserServiceImpl();
userService.addUserService();
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
2、创建UserDao.java
package com.atqt.spring.iocxm.auto.dao;
public interface UserDao {
public void addUserDao();
}
3、创建UserDaoImpl.java
package com.atqt.spring.iocxm.auto.dao;
public class UserDaoImpl implements UserDao{
@Override
public void addUserDao() {
System.out.println("UserDao方法执行了");
}
}
4、创建UserService.java
package com.atqt.spring.iocxm.auto.service;
public interface UserService {
public void addUserService();
}
5、创建UserServiceImpl.java
package com.atqt.spring.iocxm.auto.service;
import com.atqt.spring.iocxm.auto.dao.UserDao;
import com.atqt.spring.iocxm.auto.dao.UserDaoImpl;
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Override
public void addUserService() {
System.out.println("userServiceImpl方法执行了");
UserDao userDao = new UserDaoImpl();
userDao.addUserDao();
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
6、配置文件bean-auto.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean id="userController" class="com.atqt.spring.iocxm.auto.controller.UserController"-->
<!-- autowire="byType">-->
<!--<!–根据类型自动装配–>-->
<!-- </bean>-->
<!-- <bean id="userService" class="com.atqt.spring.iocxm.auto.service.UserServiceImpl"-->
<!-- autowire="byType" >-->
<!-- </bean>-->
<!-- <bean id="UserDao" class="com.atqt.spring.iocxm.auto.dao.UserDaoImpl">-->
<!-- </bean>-->
<!--根据名称自动装配-->
<bean id="userController" class="com.atqt.spring.iocxm.auto.controller.UserController"
autowire="byName">
</bean>
<bean id="userService" class="com.atqt.spring.iocxm.auto.service.UserServiceImpl"
autowire="byName">
</bean>
<bean id="UserDao" class="com.atqt.spring.iocxm.auto.dao.UserDaoImpl">
</bean>
</beans>
7、进行测试TestUser.java
package com.atqt.spring.iocxm.auto.service;
import com.atqt.spring.iocxm.auto.controller.UserController;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
@Test
public void demo01(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean-auto.xml");
UserController userController = (UserController) context.getBean("userController");
userController.addUser();
}
}
5、基于注解管理Bean
1、概念
1、java5开始增加注解的支持,是代码的特殊标记,可以在编译、类加载和运行时被读取,执行响应的处理。
2、开发人员可以通过注解在不改变原有代码和逻辑的情况下,在源代码中嵌入开发资源
3、spring2.5开始支持注解
4、我们可以使用注解实现自动装配,简化Spring和xml的配置
2、spring自动装配注解的实现步骤
1、引入依赖
2、开启组件扫描
3、使用注解定义bean
4、依赖注入
3、创建测试模块
1、创建一个模块,然后把相应的包导入
2、把log4j2.xml设置好
4、开启扫描组件
1、spring默认是不使用注解装配bean的
2、所以我们需要在spring的xml中进行配置
3、然后通过context:component-scan元素,开启Spring Beans的自动扫描功能
4、开启后就会自动的扫描指定的包,以及包下的所有类
5、如果有使用@component注解,就会将该类装到注解里面,就相当于是IOC中的把普通pojo实例化到spring容器中,相当于配置文件中的\
6、扫描组件配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描功能-->
</beans>
1、情况一:最基本的扫描方式
<!--开启组件扫描功能-->
<context:component-scan base-package="com.atqt"></context:component-scan>
2、情况二:指定要排除的组件(基本了解)
<!-- context:exclude-filter标签:指定排除规则 -->
<!--
type:设置排除或包含的依据
type="annotation",根据注解排除,expression中设置要排除的注解的全类名
type="assignable",根据类型排除,expression中设置要排除的类型的全类名
-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>
3、情况三:仅扫描指定组件
<context:component-scan base-package="com.atguigu" use-default-filters="false">
<!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
<!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
<!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
<!--
type:设置排除或包含的依据
type="annotation",根据注解排除,expression中设置要排除的注解的全类名
type="assignable",根据类型排除,expression中设置要排除的类型的全类名
-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>
5、使用注解定义Bean
1、内容
1、spring提供了以下多个注解,这些注解可以直接标注在java类上,将他们定义成Spring Bean
2、内容
| 注解 | 说明 |
|---|---|
| @Component | 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。 |
| @Repository | 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
| @Service | 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
| @Controller | 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
2、基本使用例子
1、创建一个User.java
package com.atqt.spring6.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component(value = "user") //== <bean id="user" class="xxx"
public class User {
}
2、bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描功能-->
<context:component-scan base-package="com.atqt.spring6">
<!-- context:exclude-filter标签:指定排除规则 -->
<!--
type:设置排除或包含的依据
type="annotation",根据注解排除,expression中设置要排除的注解的全类名
type="assignable",根据类型排除,expression中设置要排除的类型的全类名
-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>
<!-- 排除指定的扫描组件-->
</beans>
6、实验一:@Autowired注入
1、内容
1、单独使用@Autowired注入,根据默认类型匹配【默认是byType】
2、源码
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//使用的地方
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
//要求这个值必须存在
boolean required() default true;
}
3、可以在注入的地方一
构造方法上
方法上
形参上
属性上
注解上
4、可以注解的地方二
①该注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须是存在的
②如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系
③存在的话就注入,不存在也不报错
2、场景一:属性注入
1、对模块的xml文件进行配置扫描
2、创建UserDao.java
package com.atqt.spring6.bean.autowired.dao;
public interface UserDao {
public void add();
}
3、创建UserDaoImpl.java
package com.atqt.spring6.bean.autowired.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("UserDaoImpl执行了....");
}
}
4、UserService.java
package com.atqt.spring6.bean.autowired.service;
public interface UserService {
public void add();
}
5、UserServiceImpl.java
package com.atqt.spring6.bean.autowired.service;
import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
// 注入dao
// 第一种方式 属性注入
@Autowired
private UserDao userDao;
@Override
public void add() {
System.out.println("UserServiceImpl执行了。。。。");
userDao.add();
}
}
6、UserController.java
package com.atqt.spring6.bean.autowired.controller;
import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
// 注入Service
//方式一:第一种注入属性注入
@Autowired//根据类型找到对应的对象
private UserService userService;
public void add(){
System.out.println("UserController执行了。。。。");
userService.add();
}
}
7、测试使用注解TestUser.java
package com.atqt.spring6.bean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
User user = (User) context.getBean(User.class);
System.out.println(user);
}
}
3、场景二:set方法注入
1、基本内容和场景一类似
2、UserDao.java一样
3、UserDaoImpl一样
4、UserService.java一样
5、UserServiceImpl.java
// 第二种方式
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
6、UserController.java
package com.atqt.spring6.bean.autowired.controller;
import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
// 注入Service
// //方式一:第一种注入属性注入
// @Autowired//根据类型找到对应的对象
//private UserService userService;
// 方式二:set注入
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void add(){
System.out.println("UserController执行了。。。。");
userService.add();
}
}
7、测试使用注解TestUser.java
package com.atqt.spring6.bean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
User user = (User) context.getBean(User.class);
System.out.println(user);
}
}
4、场景三:构造方法注入
1、
1、基本内容和场景一类似
2、UserDao.java一样
3、UserDaoImpl一样
4、UserService.java一样
5、UserServiceImpl.java
package com.atqt.spring6.bean.autowired.service;
import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
// 注入dao
// 第一种方式 属性注入
// @Autowired
// private UserDao userDao;
//
// @Override
// 第二种方式
// private UserDao userDao;
//
// @Autowired
// public void setUserDao(UserDao userDao) {
// this.userDao = userDao;
// }
// 第三种方法
private UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public void add() {
System.out.println("UserServiceImpl执行了。。。。");
userDao.add();
}
}
6、UserController.java
package com.atqt.spring6.bean.autowired.controller;
import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
// 注入Service
// //方式一:第一种注入属性注入
// @Autowired//根据类型找到对应的对象
//private UserService userService;
// 方式二:set注入
// private UserService userService;
// @Autowired
// public void setUserService(UserService userService) {
// this.userService = userService;
// }
// 第三种方法:构造器注入
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
public void add(){
System.out.println("UserController执行了。。。。");
userService.add();
}
}
7、测试使用注解TestUser.java
package com.atqt.spring6.bean.autowired;
import com.atqt.spring6.bean.autowired.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
UserController userController = context.getBean(UserController.class);
userController.add();
}
}
5、场景四:构造方法注入
1、基本内容和场景一类似
2、UserDao.java一样
3、UserDaoImpl一样
4、UserService.java一样
5、UserServiceImpl.java
package com.atqt.spring6.bean.autowired.service;
import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
// 注入dao
// 第一种方式 属性注入
// @Autowired
// private UserDao userDao;
//
// @Override
// 第二种方式
// private UserDao userDao;
//
// @Autowired
// public void setUserDao(UserDao userDao) {
// this.userDao = userDao;
// }
//// 第三种方法
// private UserDao userDao;
// @Autowired
//
// public UserServiceImpl(UserDao userDao) {
// this.userDao = userDao;
// }
// 第四种方式:形参注入
private UserDao userDao;
public UserServiceImpl(@Autowired UserDao userDao) {
this.userDao = userDao;
}
public void add() {
System.out.println("UserServiceImpl执行了。。。。");
userDao.add();
}
}
6、UserController.java
package com.atqt.spring6.bean.autowired.controller;
import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
// 注入Service
// //方式一:第一种注入属性注入
// @Autowired//根据类型找到对应的对象
//private UserService userService;
// 方式二:set注入
// private UserService userService;
// @Autowired
// public void setUserService(UserService userService) {
// this.userService = userService;
// }
//// 第三种方法:构造器注入
// private UserService userService;
//
// @Autowired
// public UserController(UserService userService) {
// this.userService = userService;
// }
// 第四种方式:形参注入
private UserService userService;
public UserController(@Autowired UserService userService) {
this.userService = userService;
}
public void add(){
System.out.println("UserController执行了。。。。");
userService.add();
}
}
7、测试使用注解TestUser.java
package com.atqt.spring6.bean.autowired;
import com.atqt.spring6.bean.autowired.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
UserController userController = context.getBean(UserController.class);
userController.add();
}
}
6、场景五:只有一个有参构造函数,可以不注释!
1、注意:有且只有一个有参构造函数,才可以不注释
7、场景六:@Autowired和@Qualifier注解联合
1、UserDao一样UserService一样
2、添加一个UserRedisDaoImpl.java
package com.atqt.spring6.bean.autowired.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserRedisDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("UserRedisDaoImpl运行了....");
}
}
3、修改UserServiceImpl.java
package com.atqt.spring6.bean.autowired.service;
import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
// 第五种方法:根据两个注解进行注入
@Autowired
@Qualifier(value = "userRedisDaoImpl")
private UserDao userDao;
public void add() {
System.out.println("UserServiceImpl执行了。。。。");
userDao.add();
}
}
4、注意要写注解
7、实验二:@Resource注入
1、@Resource和 @Autowired比较
1、@Resource注解可以完成属性注入
2、@Resource注解是JDK扩展包中的,是jdk的一部分,是标准注解,更有通用性
3、Autowired注解是Spring的
4、@Resource默认是根据名称装配byName,未指定name时,使用属性名称作为name
5、如果找不到name,就会自动启动通过类型byType装配。
6、@Autowired注解默认是根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用
7、@Resource注解用在属性上、setter方法上
8、@Autowired注解,用在属性上、setter方法上、构造方法上、构造方法参数上
9、@Resource注解属于jdk扩展包,所以不做jdk当中,需要引入额外的包【jdk8不要,jdk高于11或者低于jdk8需要引入】
10、依赖
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
2、场景一:根据name注入
1、UserDaoImp.java
package com.atqt.spring6.bean.resource.dao;
import org.springframework.stereotype.Repository;
@Repository("myUserDao")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("UserDaoImpl执行了....");
}
}
2、UserRedisDaoImpl.java
package com.atqt.spring6.bean.resource.dao;
import org.springframework.stereotype.Repository;
@Repository("myUserRedisDao")
public class UserRedisDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("UserRedisDaoImpl运行了....");
}
}
3、UserServiceImpl.java
package com.atqt.spring6.bean.resource.service;
import com.atqt.spring6.bean.resource.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
@Service(value = "myUserService")
public class UserServiceImpl implements UserService {
@Resource(name = "myUserDao")
private UserDao myUserDao;
public void add() {
System.out.println("UserServiceImpl执行了。。。。");
myUserDao.add();
}
}
4、TestUser.java
package com.atqt.spring6.bean.resource;
import com.atqt.spring6.bean.resource.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
UserController userController = context.getBean(UserController.class);
userController.add();
}
}
3、测试异常
1、根据异常信息得知:显然当通过name找不到的时候,自然会启动byType进行注入,以上的错误是因为UserDao接口下有两个实现类导致的。所以根据类型注入就会报错。
2、@Resource的set注入可以自行测试
4、总结
1、@Resource注解:默认byName注入,没有指定name时把属性名当做name,根据name找不到时,才会byType注入。byType注入时,某种类型的Bean只能有一个