Java:Spring的IOC 测试活动:Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
装配和注入是什么关系
- 注入包含着装配。注入能注入bean和普通属性,装配是用来bean之间的操作也就是注入bean。
类、Bean、对象、实例的关系
-

类可以生成对象/实例。Bean只能生成实例。
IOC怎么做到低耦合
- 外围用工厂模式,工厂里面使用xml解析和反射技术
Spring 的IOC的工作流程是什么?
- 先配置xml文件让对象创建出来
- 在类中解析xml文件
- 通过反射和xml得到的类名将对象创建出来
什么是IOC容器
- IOC容器底层就是工厂模式
Spring创建IOC容器的两种方式
- BeanFactory和ApplicationContext
BeanFactory和ApplicationContext的异同是什么?
- BeanFactory和ApplicationContext都是IOC容器的基本实现。
- BeanFactory是Spring内部使用的接口。它加载文件的时候不创建对象,只有在对象使用的时候才会创建对象。
- ApplicationContext是BeanFactory的子接口,提供更多的功能。一般由开发人员使用。在加载配置文件的时候就会创建对象。
BeanFactory和ApplicationContext哪一个推荐使用
- ApplicationContext更推荐使用。因为在后续web开发的时候,创建对象这种费时费力的操作尽量在服务器启动的时候完成。
ApplicationContext的两个实现类有什么区别
-

-
FileSystemXmlApplicationContext中调用Xml的路径填的是绝对路径
-
ClassPathXmlApplicationContext中调用Xml的路径是调用方法的类的相对路径
什么是IOC操作Bean管理
- Bean管理指的是Spring创建对象和Spring注入属性
Bean管理的两种方式
- Xml配置文件实现
- 注解方式实现
Xml配置文件实现创建对象

- 在spring的xml文件中使用标签就能创建对象
Xml中的Bean标签有很多属性
- id 属性:唯一标识,不能和 name 标签相同。
- class 属性:类全路径(包类路径)
- name 属性:唯一标识,能使用特殊符号,不能与 id 标签相同。
Xml中Bean标签的注意点
- 默认使用无参构造函数创建对象。如果类中重写了有参构造函数但是Xml中没有标识会报错。
什么是DI
- DI就是依赖注入,也是属性注入。可以理解为给类的属性赋值。
常用的属性注入方法有哪些
- 通过属性的 set 方法来实现
- 通过有参构造方法来实现
在 Xml 配置文件中怎么给 Bean 怎么通过 set 方法注入属性?
-
先创建类的属性和对应的 set 方法
package com.atguigu.spring5; /** * 演示使用set方法进行注入属性 */ public class Book { //创建属性 private String bname; private String bauthor; private String address; //创建属性对应的set方法 public void setBname(String bname) { this.bname = bname; } public void setBauthor(String bauthor) { this.bauthor = bauthor; } public void setAddress(String address) { this.address = address; } public void testDemo() { System.out.println(bname+"::"+bauthor+"::"+address); } } -
在 Xml 配置文件中创建对象,在标签中添加 name 属性和 value 属性。它们分别代表类属性的名称和属性注入的值。多个属性注入就需要写多个标签并添加对应的 name 属性和 value 属性。
<!--2 set方法注入属性--> <bean id="book" class="com.atguigu.spring5.Book"> <!--使用property完成属性注入 name:类里面属性名称 value:向属性注入的值 --> <property name="bname" value="易筋经"></property> <property name="bauthor" value="达摩老祖"></property> </bean>
在 Xml 配置文件中怎么给 Bean 怎么通过 有参构造方法 注入属性?
-
先创建类的属性和对应的 有参构造方法
package com.atguigu.spring5; /** * 使用有参数构造注入 */ public class Orders { //属性 private String oname=""; private String address; //有参数构造 public Orders(String oname,String address) { this.oname = oname; this.address = address; } public void ordersTest() { System.out.println(oname+"::"+address); } } -
在 Xml 配置文件中创建对象,在 标签中添加 name 属性和 value 属性。它们分别代表类属性的名称和属性注入的值。多个属性注入就需要写多个 标签并添加对应的 name 属性和 value 属性。
<!--3 有参数构造注入属性--> <bean id="orders" class="com.atguigu.spring5.Orders"> <!--使用constructor-arg完成属性注入 name:类里面属性名称 value:向属性注入的值 --> <constructor-arg name="oname" value="电脑"></constructor-arg> <constructor-arg name="address" value="China"></constructor-arg> </bean> -
了解。在 标签中还可以添加 index 属性和 value 属性。
<!--3 有参数构造注入属性-->
<bean id="orders" class="com.atguigu.spring5.Orders">
<!--使用property完成属性注入
index:类里面属性的下标
value:向属性注入的值
-->
<constructor-arg index="0" value="电脑"></constructor-arg>
<constructor-arg index="1" value="China"></constructor-arg>
</bean>
什么是字面量
- 类中的属性在声明的时候初始化
- 类中的属性在 Xml 配置文件中的属性注入
- 可以理解为对象中某些属性声明时初始化。
怎么在 Xml 配置文档中给属性初始化一个 null
-
在 set 方法中把标签中的 value 属性去除,并填入一个 标签。
<!--null值--> <property name="address"> <null/> </property>
怎么在 Xml 配置文件中给属性带有特殊符号的初始化
-
在 set 方法中把标签中
-
把 value 属性里写入特殊符号的转义符号
-
把标签中的 value 属性去除,填入一个标签。在标签中填入
<!--属性值包含特殊符号 1 把<>进行转义 < > 2 把带特殊符号内容写到CDATA --> <property name="address"> <value><![CDATA[特殊符号的value值]]></value> </property>
-
怎么在 Xml 配置文件中给一个对象注入外部 Bean
-
有两个包,分别是 Service 和 Dao
Service 包中包含了 UserService 类
Dao 包含了 UserDao 接口和它的实现类 UserDaoImpl
UserService 类里调用 UserDao 类,通过多态所以使用了 UserDaoImpl 里的方法
所以我们需要在 UserService 类调用 UserDao 类

UserService 类
package com.atguigu.spring5.service; import com.atguigu.spring5.dao.UserDao; import com.atguigu.spring5.dao.UserDaoImpl; public class UserService { //创建UserDao类型属性,生成set方法 private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add() { System.out.println("service add..............."); userDao.update(); } }UserDao 类
package com.atguigu.spring5.dao; public interface UserDao { public void update(); }UserDaoImpl 类
package com.atguigu.spring5.dao; public class UserDaoImpl implements UserDao { @Override public void update() { System.out.println("dao update..........."); } } -
方法
-
先在要调用的类里创建一个被调用类的属性,并给出对应的 set 方法
package com.atguigu.spring5.service; import com.atguigu.spring5.dao.UserDao; import com.atguigu.spring5.dao.UserDaoImpl; public class UserService { //创建UserDao类型属性,生成set方法 private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add() { System.out.println("service add..............."); userDao.update(); } } -
在 Xml 配置文件中,创建一个调用类的对象和一个被调用类的对象,在调用类对象的标签中添加 name 和 ref 属性。name 和 ref 属性分别代表 被调用类的属性名 和 被调用类id。
特别注意,这里使用了多态所以被调用的 name 是 userDao,被调用类 id 是 userDaoImpl。
<!--1 service和dao对象创建--> <bean id="userService" class="com.atguigu.spring5.service.UserService"> <!--注入userDao对象 name属性:类里面属性名称 ref属性:创建userDao对象bean标签id值 --> <property name="userDao" ref="userDaoImpl"></property> </bean> <bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>上面这一步等同于。注意 UserDao userDao = new UserDaoImpl(); 这一句就代表了 name 和 id。
package com.atguigu.spring5.service; import com.atguigu.spring5.dao.UserDao; import com.atguigu.spring5.dao.UserDaoImpl; public class UserService { public void add() { System.out.println("service add..............."); UserDao userDao = new UserDaoImpl(); userDao.update(); } }
-
怎么在 Xml 配置文件中给对象注入内部 Bean
-
一个班主任老师带领多个学生,每个学生都对应一个班主任老师。
所以我们可以在学生的属性中添加班主任老师类

所以我创建了 Teacher 类和 Student 类,下面是代码实现。
Teacher 类
package cn.hyz.bean; /** * @author workplace * @date 2022/3/5 11:28 */ public class Teacher { private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "Teacher{" + "name='" + name + '\'' + '}'; } }Student 类
package cn.hyz.bean; import com.sun.corba.se.impl.orb.ParserTable; /** * @author workplace * @date 2022/3/5 11:28 */ public class Student { private String name; private String nation; private Teacher teacher; public void setName(String name) { this.name = name; } public void setNation(String nation) { this.nation = nation; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } public void say() { System.out.println(name + " " + nation + " " + teacher.toString()); } } -
我们现在通过 Xml 配置文件创建一个 Student 类的对象
-
现在 Student 中创建一个 Teacher 类的属性
-
在 Xml 配置文件中,创造一个 Student 类的对象,并且在 teacher 属性中嵌套了 Teacher 类的对象。
<property name="teacher"> <bean class="cn.hyz.bean.Teacher" id="teacher"> <property name="name" value="老师"></property> </bean> </property><?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="student" class="cn.hyz.bean.Student"> <property name="name" value="何雅梓"></property> <property name="nation" value="中国"></property> <property name="teacher"> <bean class="cn.hyz.bean.Teacher" id="teacher"> <property name="name" value="老师"></property> </bean> </property> </bean> </beans>
-
级联赋值是什么
-
一个班主任老师带领多个学生,每个学生都对应一个班主任老师。
所以我们可以在 Student 的属性中添加 Teacher
Teacher类
package cn.hyz.bean; /** * @author workplace * @date 2022/3/5 16:26 */ public class Teacher { private String name; public void setName(String name) { this.name = name; } public String say() { return ("我的老师是:" + name); } }Student类
package cn.hyz.bean; /** * @author workplace * @date 2022/3/5 16:26 */ public class Student { private String name; private int age; private Teacher teacher; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } public void say() { System.out.println("我的名字是:" + name + ",我的年龄是:" + age + teacher.say()); } } -
级联赋值就是类中要使用另一个类的属性,所以要获取和修改另一个类的属性。
-
我们现在通过 Xml 配置文件创建一个 Student 类的对象
-
我们先在创建一个 Teacher 类的属性和对应的 get set 方法
-
再创建 Student 类,并加入 Teacher 类属性。
-
创建 Xml 配置文件
在 Student 对象的 的标签里创建 name 属性和 value 属性。下面就是级联赋值的例子。name 属性里填入的是 外部 Bean.属性名,value 属性里填入的是 修改的值。

<?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="teacher" class="cn.hyz.bean.Teacher"> <property name="name" value="何冠德"></property> </bean> <bean id="student" class="cn.hyz.bean.Student"> <property name="name" value="何雅梓"></property> <property name="age" value="21"></property> <property name="teacher" ref="teacher"/> <property name="teacher.name" value="级联赋值"></property> </bean> </beans>
-
注入外部Bean 和 注入内部Bean 和 级联赋值
-
注入外部Bean
-
注入外部Bean是通过 Xml 配置文件创建了 类A 和 类B,然后 类B 作为一个属性注入 类A里面。
就是有一个类A和一个类B。类B在类A中是属性并有对应的set方法。先创建类A和类B对象。在把类B作为实参传入类A的set方法,就可以在类A中调用类B的属性和方法了。

<bean id="类A" class="类A地址"> <property name="属性a的名称" value="属性a的值"></property> <property name="类B名称lb" ref="类B的id"></property> </bean> <bean id="类B" class="类B地址"> <property name="属性b的名称" value="属性b的值"></property> </bean>在 Java 中用代码实现就是
class A { private int a; private B lb; public void setA(int a) { this.a = a; } public void setLb(B lb) { this.lb = lb; } public void testSay() { System.out.println(a + "::" + lb.b); } } class B { private int b; public void setB(int b) { this.b = b; } } @Test public void test() { A a = new A(); a.setA(1); B b = new B(); b.setB(2); a.setLb(b); a.testSay(); }
-
-
注入内部Bean
-
注入外部Bean是通过 Xml 配置文件创建了 类A ,然后 类B 作为一个属性在 类A 里创建。
先创建类A和A的内部类类B。类B在类A中是属性并有对应的set方法。通过在类A的方法中创建类B的对象就可以调用类B的属性和方法。

<bean id="类A" class="类A地址"> <property name="属性a的名称" value="属性a的值"></property> <property name="类B名称lb"> <bean id="类B" class="类B地址"> <property name="属性b的名称" value="属性b的值"></property> </bean> </property> </bean>在 Java 中用代码实现
class A { private int a; private B bl; class B { private int b; public void setB(int b) { this.b = b; } } public void setBl() { B lb = new B(); lb.setB(2); this.bl = lb; } public void setA(int a) { this.a = a; } public void testSay() { B b = new B(); b.setB(2); System.out.println(a + "::" + bl.b); } } @Test public void test() { A a = new A(); a.setA(1); a.setBl(); a.testSay(); } -
级联赋值
-
注入外部Bean是通过 Xml 配置文件创建了 类A 和 类B,然后 类B 作为一个属性注入 类A里面。类A 对 类B 有 get set 方法。这样子就能获取了 类A 中的 类B 然后调用 类B 的 set 方法来修改 类B 的属性。

<bean id="类A" class="类A地址"> <property name="属性a的名称" value="属性a的值"></property> <property name="类B名称lb" ref="类B的id"></property> <property name="类B名称.属性名b" value="属性b的值"></property> </bean> <bean id="类B" class="类B地址"> <property name="属性b的名称" value="属性b的值"></property> </bean>在 Java 中用代码实现
class A { private int a; private B lb; public void setA(int a) { this.a = a; } public B getLb() { return lb; } public void setLb(B lb) { this.lb = lb; } public void testSay() { System.out.println(a + "::" + lb.b); } } class B { private int b; public void setB(int b) { this.b = b; } } @Test public void test() { A a = new A(); a.setA(1); B b = new B(); b.setB(1); /* 级联赋值就是获取了类A中的类B然后调用类B的set方法来修改类B的属性 */ a.setLb(b); a.getLb().setB(2); a.testSay(); }
-
-
Xml 配置文件中怎么注入数组、List、Map 和 Set 属性
-
在类中有着数组、List、Map 和 Set 类型的属性,我们可以在 Xml 配置文件中去创建对象并注入属性
示范类
package cn.hyz.bean; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; /** * @author workplace * @date 2022/3/6 10:29 * 创建出 数组、list、map、set 类型的属性,并给出对应的 set 方法 */ public class ArrayBean { private String[] var1; private List<String> var2; private Map<String,String> var3; private Set<String> var4; public void setVar1(String[] var1) { this.var1 = var1; } public void setVar2(List<String> var2) { this.var2 = var2; } public void setVar3(Map<String, String> var3) { this.var3 = var3; } public void setVar4(Set<String> var4) { this.var4 = var4; } public void test() { System.out.println(Arrays.toString(var1)); System.out.println(var2); System.out.println(var3); System.out.println(var4); } }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="arrayBean" class="cn.hyz.bean.ArrayBean"> <!--数组属性注入--> <property name="var1"> <array> <value>var1_1</value> <value>var1_2</value> </array> </property> <!--list属性注入--> <property name="var2"> <list> <value>var2_1</value> <value>var2_2</value> </list> </property> <!--map属性注入--> <property name="var3"> <map> <entry key="var3_1_1" value="var3_1_2"></entry> <entry key="var3_2_1" value="var3_2_2"></entry> </map> </property> <!--set属性注入--> <property name="var4"> <set> <value>var4_1</value> <value>var4_2</value> </set> </property> </bean> </beans>测试类
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.lang.annotation.Target; import java.util.Arrays; /** * @author workplace * @date 2022/3/6 10:34 */ public class ArrayBeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class); arrayBean.test(); } }测试结果
[var1_1, var1_2] [var2_1, var2_2] {var3_1_1=var3_1_2, var3_2_1=var3_2_2} [var4_1, var4_2]可以看到注入的属性全部输出了。表示 Xml 配置文件注入属性成功
Xml 配置文件中怎么在集合里面设置对象类型值
-
示范类
集合中要用到的类
package cn.hyz.bean; /** * @author workplace * @date 2022/3/6 11:08 */ public class Bean { private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "Bean{" + "name='" + name + '\'' + '}'; } }集合使用类
package cn.hyz.bean; import java.util.List; /** * @author workplace * @date 2022/3/6 10:29 * 创建出 数组、list、map、set 类型的属性,并给出对应的 set 方法 */ public class ArrayBean { /** * 生成一个泛型是 Bean 类的 List 类型的属性并给出对应的 set 方法 */ private List<Bean> beanList; public void setBeanList(List<Bean> beanList) { this.beanList = beanList; } public void test() { System.out.println(beanList); } }Xml 配置文件注入属性。注意这里在 List 中的属性注入用的标签是 用 bean 属性指向对象的 id 属性。
<?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"> <!--在集合里面设置对象类型值--> <!--1. 创建多个 Bean 对象--> <bean id="bean1" class="cn.hyz.bean.Bean"> <property name="name" value="bean1"/> </bean> <bean id="bean2" class="cn.hyz.bean.Bean"> <property name="name" value="bean2"/> </bean> <!--2. 在 ArrayBean 中对 List 类型属性注入,用 ref 中的 bean 属性来指向注入的 Bean 元素--> <bean id="arrayBean" class="cn.hyz.bean.ArrayBean"> <property name="beanList"> <list> <ref bean="bean1"></ref> <ref bean="bean2"></ref> </list> </property> </bean> </beans>测试类
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/6 10:34 */ public class ArrayBeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class); arrayBean.test(); } }结果
[Bean{name='bean1'}, Bean{name='bean2'}]可以看到注入的属性全部输出了。表示 Xml 配置文件注入属性成功。
Xml 配置文件中怎么把集合注入部分提取出来
-
示范类
集合中要用到的类
package cn.hyz.bean; /** * @author workplace * @date 2022/3/6 11:08 */ public class Bean { private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "Bean{" + "name='" + name + '\'' + '}'; } }集合使用类
package cn.hyz.bean; import java.util.List; /** * @author workplace * @date 2022/3/6 10:29 * 创建出 数组、list、map、set 类型的属性,并给出对应的 set 方法 */ public class ArrayBean { /** * 生成一个泛型是 Bean 类的 List 类型的属性并给出对应的 set 方法 */ private List<Bean> beanList; public void setBeanList(List<Bean> beanList) { this.beanList = beanList; } public void test() { System.out.println(beanList); } }Xml 配置文件注入属性。
- 首先进行名称导入
- 然后 <util:类型></util:类型> 标签进行集合提取,选择类型之后用 id 属性进行标识
- 在对象中进行属性注入,通过 ref 属性指向集合的 id 就可以进行属性注入了。
<?xml version="1.0" encoding="UTF-8"?> <!--1. 名称空间引入 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 http://www.springframework.org/schema/util/spring-util.xsd"> --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" 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 http://www.springframework.org/schema/util/spring-util.xsd"> <!--2. 集合注入部分提取,在 util:类型并用 id 属性标识--> <util:list id="list"> <value>"var1"</value> <value>"var2"</value> <value>"var3"</value> <value>"var4"</value> <value>"var5"</value> </util:list> <!--3. 对象的属性注入,ref 属性用集合提取的 id 作为识别--> <bean id="arrayBean" class="cn.hyz.bean.ArrayBean"> <property name="var2" ref="list"></property> </bean> </beans>测试类
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/6 10:34 */ public class ArrayBeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class); arrayBean.test(); } }结果
["var1", "var2", "var3", "var4", "var5"]可以看到注入的属性全部输出了。表示 Xml 配置文件注入属性成功。
什么是工厂Bean(Factory Bean)
- 一种特殊的 bean,在 xml 文件中配置的,用来生成新的 bean 的加工厂,通过 getObject() 方法可以获取其生产的新 bean,如果想获取该工厂 bean 本身,需要使用类似于
getBean("&" + beanName)的样式。
工厂 Bean(Factory Bean)和普通 Bean 有什么区别
- 普通 Bean 在 Xml 配置文件中定义的 Bean 类型就是返回类型,即通过 Xml 配置文件创建出来的对象的类型。其中的
ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class);的ArrayBean就是返回类型。 - 工厂Bean(Factory Bean)在 Xml 配置文件中定义的 Bean 类型可以和返回类型不同。
如何实现工厂 Bean
-
创建实现类并实现 FactoryBean<Object> 接口并重写方法。
package cn.hyz.factoryBean; import cn.hyz.bean.ArrayBean; import org.springframework.beans.factory.FactoryBean; import java.util.ArrayList; /** * @author workplace * @date 2022/3/6 16:56 * 创建工厂 Bean,需要实现 FactoryBean<Object> 接口并重写方法。 * 将接口后面的 <Object> 填写为想要通过工厂 Bean 去获取的类 */ public class Bean implements FactoryBean<ArrayBean> { /** * 然后修改 getObject() 的类型和返回值即可获取到想要的类 * @return 想要的类 * @throws Exception */ @Override public ArrayBean getObject() throws Exception { ArrayBean arrayBean = new ArrayBean(); ArrayList<String> strings = new ArrayList<>(); strings.add("1"); strings.add("2"); arrayBean.setVar2(strings); return arrayBean; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } } -
然后在 Xml 配置文件中创建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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="cn.hyz.factoryBean.Bean" id="bean"></bean> </beans> -
最后再测试类将对象创建出来。我们传入的 Class对象 和 创建类型 也需要修改成我们想要的那个类。
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/6 17:02 */ public class BeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); /** * 这里因为是用了工厂 bean 并且修改 getObject() 的类型和返回值 * 所以我们传入的 Class对象 和 创建类型 也需要修改成我们想要的那个类 */ ArrayBean bean = context.getBean("bean", ArrayBean.class); bean.test(); } } -
测试结果
[1, 2] -
补充:想要的那个类的代码
package cn.hyz.bean; import java.util.List; /** * @author workplace * @date 2022/3/6 10:29 */ public class ArrayBean { private List<String> var2; public void setVar2(List<String> var2) { this.var2 = var2; } public void test() { System.out.println(var2); } }
Bean 的作用域是什么
-
在 Spring 中,bean 作用域用于确定哪种类型的 bean 实例应该从 Spring 容器中返回给调用者。
-
作用域 描述 singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。 prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。 request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。 session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。 application 限定一个Bean的作用域为 ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。 -
目前常用的是 singleton 和 prototype。默认是 singleton 作用域。
-
singleton 作用阈测试
测试类
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/6 17:02 */ public class BeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); // 同时创造两个对象看地址是否相同 ArrayBean bean1 = context.getBean("bean", ArrayBean.class); ArrayBean bean2 = context.getBean("bean", ArrayBean.class); System.out.println(bean1); System.out.println(bean2); } }结果
cn.hyz.bean.ArrayBean@1e7c7811 cn.hyz.bean.ArrayBean@1e7c7811
如何设置作用域
-
在 Xml 配置文件中我们对于 <bean></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 标签里添加了 scope 属性并选择了 prototype--> <bean class="cn.hyz.factoryBean.Bean" id="bean" scope="prototype"></bean> </beans>测试类
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/6 17:02 */ public class BeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); ArrayBean bean1 = context.getBean("bean", ArrayBean.class); ArrayBean bean2 = context.getBean("bean", ArrayBean.class); System.out.println(bean1); System.out.println(bean2); } }结果
cn.hyz.bean.ArrayBean@4923ab24 cn.hyz.bean.ArrayBean@44c8afef可以看出两个对象的地址都不一样。
singleton 作用域和 prototype 作用域的区别是什么?
- singleton 表示单实例,prototype 表示多实例
- singleton 是在加载 Xml 配置文件的时候就创建单实例对象。而 prototype 则是在调用
getBean()方法的时候才会创建多实例对象。
Spring 生命周期是什么
- 通过无参构造器创建 bean 实例
- 通过 Xml 配置文件为 bean 注入属性和对其他 bean 引用(调用 set 方法)
- 调用 bean 初始化方法(需要配置初始化的方法)
- 使用 bean 生成对象
- 容器关闭,调用 bean 的销毁方法(需要配置销毁的方法)
-
例子
package cn.hyz.bean; /** * @author workplace * @date 2022/3/6 10:29 */ public class ArrayBean { private String var2; /** * 默认自动生成无参构造方法,为了演示所以写了 */ public ArrayBean() { System.out.println("第一步:执行无参构造方法创建 bean 实例"); } public void setVar2(String var2) { this.var2 = var2; System.out.println("第二步:调用 set 方法设置属性值"); } /** * 手动创建初始化方法 */ public void initMethod() { System.out.println("第三步:执行初始化方法"); } /** * 手动创建销毁方法 */ public void destroyMethod() { System.out.println("第五步:执行销毁的方法"); } public void test() { System.out.println(var2); } }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"> <!--添加 init-method destroy-method 属性--> <bean id="arrayBean" class="cn.hyz.bean.ArrayBean" init-method="initMethod" destroy-method="destroyMethod"> <property name="var2" value="123abc"></property> </bean> </beans>测试类
package cn.hyz.beanTest; import cn.hyz.bean.ArrayBean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/6 10:34 */ public class ArrayBeanTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml"); ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class); System.out.println("第四步,获取创建 bean 实例对象"); System.out.println(arrayBean); /** * 手动让 bean 实例销毁。 */ ((ClassPathXmlApplicationContext) context).close(); } }结果
第一步:执行无参构造方法创建 bean 实例 第二步:调用 set 方法设置属性值 第三步:执行初始化方法 第四步,获取创建 bean 实例对象 cn.hyz.bean.ArrayBean@c81cdd1 第五步:执行销毁的方法
什么是后置处理器
- 后置处理器就是在 bean 对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。
- 通过无参构造器创建 bean 实例
- 通过 Xml 配置文件为 bean 注入属性和对其他 bean 引用(调用 set 方法)
- 把 bean 实例传递 bean 后置处理器的方法:postProcessBeforeInitialization(Object bean, String beanName)
- 调用 bean 初始化方法(需要配置初始化的方法)
- 把 bean 实例传递 bean 后置处理器的方法:postProcessAfterInitialization(Object bean, String beanName)
- 使用 bean 生成对象
- 容器关闭,调用 bean 的销毁方法(需要配置销毁的方法)
如何创建后置处理器
- 创建类,实现接口
BeanPostProcessor并重写方法即可 - 然后在 Xml 配置文件中创建
Bean,就会为这个 Xml 配置文件中的所有Bean创建后置处理器。当创建Bean对象并运行的时候,就会在调用初始化之前和之后去调用后置处理器的重写方法,利于程序员添加自己的逻辑。
Xml 自动装配
-
当一个
bean需要用到其他bean作为属性的时候,不再需要手动外部注入而是会自动注入。autowire属性包含了byType和byName两种。这里引用了spring——自动装配【非常详细】 - 白熊啊 - 博客园 (cnblogs.com)
1.byName
设置autowire属性为byName,那么Spring会根据class属性找到实体类,然后查询实体类中所有setter方法的名字,根据setter方法后面的名字(例如SetDog,则setter方法后面的名字为dog)再到配置文件中寻找一个与该名字相同id的Bean,注入进来

2.byType
设置autowire属性为byType,那么Spring会自动寻找一个与该属性类型相同的Bean,注入进来。

IoC基于注解操作bean管理
-
什么是注解
-
什么是注解
- 注解是特殊格式的代码
-
注解的使用范围是多大啊
- 注解能在类上使用;能在方法上使用;能在属性上使用
-
为什么使用注解
- 能让 Xml 配置文件更加的简洁
-
-
Spring针对Bean管理中创建对象提供了四个注解-
@Component
-
@Service
-
@Controller
-
@Repository
- 四个注解功能都是一样的,都可以用来创建
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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
第二步:开启组件扫描。
通过创建**<context:component-scan></context:component-scan>**标签,选择属性(base-package) 填入包名,通过单个或多个达到开启组件扫描的结果。
如果是同一目录下的多个包,1.2和1.3的效果是一样的。
<!--开启组件扫描--> <!--1.1 单个包开启组件扫描 属性(base-package)中填入单个package.path--> <context:component-scan base-package="com.atguigu.spring5.testdemo"></context:component-scan> <!--1.2 多个包同时开启组件扫描 属性(base-package)中填入多个package.path,不同package.path之间用','隔开--> <context:component-scan base-package="com.atguigu.spring5.dao ,com.atguigu.spring5.service"></context:component-scan> <!--1.3 多个包同时开启组件扫描 属性(base-package)中填入多个package的同一个上层目录--> <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
-
第三步:创建类,在类上添加创建对象的注解。
这里创建了一个名叫 UserService 的类并且使用了 @Component 的注解来创建对象。 @Component 里的属性 (value) 可以省略,默认是类名的小驼峰。
@Component(value = "userService") 的写法和 <bean id="value填的值" calss="package.path.className"></bean> 的写法是类似的
package com.atguigu.spring5.service; import org.springframework.stereotype.Component; /** * @author workplace * @date 2022/3/7 17:40 * 1. @Component(value = "userService") 的写法和 <bean id="value填的值" calss="package.path.className"></bean> 的写法是类似的 * 2. @Component(value = "userService") 的属性 (value) 可以省略,默认是 className 的小驼峰写法 */ @Component(value = "userService") public class UserService { public void add() { System.out.println("UserService......"); } }
-
经过三个步骤我们便通过注解为类创建了对象,接下来我们测试一下
package com.atguigu.spring5.testdemo; import com.atguigu.spring5.service.UserService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/7 17:40 */ public class SpringDemoTest { @Test public void testUserService() { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); } }
结果
com.atguigu.spring5.service.UserService@b62fe6d UserService......
-
总结:这是大致的流程

我们首先引入依赖,开启组件扫描,通过注解给类创建对象。就可以通过注解来创建bean了。
-
-
开启组件扫描的细节
-
示例一
<!-- 示例一 use-default-filters="false" 表示现在不使用默认 filters,自己配置 filters context:include-filter 设置哪些内容需要扫描 这一段的意思是:我 package 除了 context:include-filter 之外什么都不扫描。 --> <context:component-scan base-package="com.atguigu" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>在开启扫描的时候可以添加属性 (use-default-filters),用来选择是否使用默认扫描。
(use-default-filters) 是 true 表示使用默认扫描,扫描 package 下的全部类看是否有注解生成 bean。
(use-default-filters) 是 false 表示不使用默认扫描,通过 <context:include-filter></context:include-filter> 标签设置哪些内容需要扫描
-
实例二
<!-- 实例二 现在使用默认 filters,扫描下面 package 的全部类 context:exclude-filter 设置哪些内容不需要扫描 这一段的意思就是:我 package 里的除了 context:exclude-filter 之外其他的都扫描。 --> <context:component-scan base-package="com.atguigu"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>这里没有设置 (use-default-filters) 所以选择了默认扫描。
通过 <context:exclude-filter></context:exclude-filter> 标签设置哪些内容不需要扫描。
-
-
Spring针对Bean管理中属性注入提供了三个注解-
@Autowired:根据属性类型进行自动装配(针对对象类型)
-
@Qualifier:根据属性名称进行自动注入(针对对象类型)
-
@Resource:可以根据类型注入,可以根据名称注入(针对对象类型)
-
@Value:注入普通类型属性(针对普通类型)
-
-
基于注解方式实行属性注入
-
用 @Autowired 作为示范
-
通过三个类之间的交流,实现自动装配。
UserDao 类
package com.atguigu.spring5.dao; /** * @author workplace * @date 2022/3/7 21:20 */ public interface UserDao { /** * */ void say(); }UserDaoImpl 类
package com.atguigu.spring5.dao; import org.springframework.stereotype.Repository; /** * @author workplace * @date 2022/3/8 15:21 */ @Repository public class UserDaoImpl implements UserDao{ @Override public void say() { System.out.println("UserDaoImpl ......"); } }UserService 类:展示了通过注解实现 bean 的自动装配。可以看出这种方法是不需要用到 set 方法。
package com.atguigu.spring5.service; import com.atguigu.spring5.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service(value = "userService") public class UserService { /** * 展示了通过注解实现 bean 的自动装配。 * 创建 dao 类属性 * 不需要添加 set 方法。 * 注解里面包含了添加、注入的操作 */ @Autowired private UserDao userDao; public void add() { // 测试 @Autowired 标签是否将类自动注入 userDao.say(); System.out.println("UserService......"); } }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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <context:component-scan base-package="com.atguigu.spring5"/> </beans>测试类
package com.atguigu.spring5.testdemo; import com.atguigu.spring5.service.UserService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/7 17:40 */ public class SpringDemoTest { @Test public void testUserService() { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); } }结果:
com.atguigu.spring5.service.UserService@22635ba0 UserDaoImpl ...... UserService......
可以看到通过注解创建对象全部成功,并且通过注解实现了 bean 的自动装配。

-
-
用 @Qualifier 作为示范
-
整体使用和 @Autowired 类似。区别在于它是根据属性名称进行自动注入,都是配合 @Autowired 一起使用。接下来我们继续用上面的例子稍做修改进行演示
UserDao 类
package com.atguigu.spring5.dao; /** * @author workplace * @date 2022/3/7 21:20 */ public interface UserDao { /** * */ void say(); }UserDaoImpl 类
package com.atguigu.spring5.dao; import org.springframework.stereotype.Repository; /** * @author workplace * @date 2022/3/8 15:21 */ @Repository(value = "userDaoImpl") public class UserDaoImpl implements UserDao{ @Override public void say() { System.out.println("UserDaoImpl ......"); } }UserService 类:展示了通过注解实现 bean 的自动装配。可以看出这种方法是不需要用到 set 方法。
package com.atguigu.spring5.service; import com.atguigu.spring5.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service(value = "userService") public class UserService { /** * 创建 dao 类属性 * 不需要添加 set 方法。 * 注解里面包含了添加、注入的操作 */ @Autowired @Qualifier(value = "userDaoImpl") private UserDao userDao; public void add() { // 测试 @Autowired 标签是否将类自动注入 userDao.say(); System.out.println("UserService......"); } }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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <context:component-scan base-package="com.atguigu.spring5"/> </beans>测试类
package com.atguigu.spring5.testdemo; import com.atguigu.spring5.service.UserService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/7 17:40 */ public class SpringDemoTest { @Test public void testUserService() { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); } }结果
com.atguigu.spring5.service.UserService@23f7d05d UserDaoImpl ...... UserService......
可以看到这里是通过获取 bean 的名称来进行装配

-
-
用 @Value 作为示范
-
这个注解常用于普通类型属性上。就是 @Value(value = "符合类型的值") 这样子就可以为普通类型进行属性注入。
UserService 类
package com.atguigu.spring5.service; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class UserService { @Value(value = "1234") private String str; @Value(value = "123") private int num; public void add() { System.out.println(str); System.out.println(num); } }SpringDemoTest 测试类
package com.atguigu.spring5.testdemo; import com.atguigu.spring5.service.UserService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author workplace * @date 2022/3/7 17:40 */ public class SpringDemoTest { @Test public void testUserService() { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); userService.add(); } }结果
1234 123
-
-
-