目录
一、配置文件(XML)中定义与配置bean。
(1)bean的基础配置。(id、class)
(2)bean的别名配置。
1、基本介绍。
2、demo测试。
3、NoSuchBeanDefinitionException!
(3)bean作用范围配置。
1、基本介绍。
2、demo测试。
3、为什么spring容器默认bean为singleton(单例)?
<1>基本解释。
<2>适合交给spring容器管理的bean。
<3>不适合交给容器进行管理的bean。
(4)bean其他属性配置(初始化、销毁等等)
二、IoC与DI的入门案例。
(1)demo的前提须知。
1、项目准备工作。
2、项目要求。
3、spring提供的二种容器(实例化与管理bean)。
(2)pom文件引入(spring-context)坐标依赖。
(3)spring配置文件(配置相应bean)。
(4)实体类"A"、实体类"B"。
1、ApplicationContext(IoC容器)。
2、BeanFactory(Bean工厂)。
(5)运行结果。
一、配置文件(XML)中定义与配置bean。
(1)bean的基础配置。(id、class)
bean基本属性。(表格)
类别 基本描述 名称 bean 类型 标签(<bean>) 所属 标签<beans>内 功能简介 定义spring核心容器的管理的对象 格式
(位于spring配置文中)
<?xml .....>
<beans>
<bean/>或
<bean></bean>(常用)
<beans>基本属性 id:bean的id(唯一标识)。使用spring容器可以通过id值获取对应的bean,在一个容器中id的值是唯一的!
class:bean的类型。配置的是bean的全路径类名。基本示例
(controlle层)
(service层) <!--配置UserService对象--> <bean id="userService" class="com.fs.service.UserService"></bean> <!--配置UserController对象--> <bean id="userController" class="com.fs.controller.UserController"> <!--配置属性值(通过setter方式实现依赖注入)--> <property name="userService" ref="userService"></property> </bean>
(2)bean的别名配置。
1、基本介绍。
- 属性名:name。
- 与id的功能基本一致。其中别名可以与id一起出现,且可以有多个,使用逗号隔开!
类别 描述 名称 name 类型 属性 所属 标签<bean>的基本属性 功能 定义bean的别名。
可以定义多个,且可以使用逗号(,)、分号(;)、空格进行分隔!
示例 <!--配置生产UserService对象--> <!--id只能有一个,name(别名)可以多个--> <bean id="userService" name="service" class="com.fs.service.UserService"> </bean> <!--配置生产UserController对象--> <!--id只能有一个,name(别名)可以多个--> <bean id="userController" name="controller controller2" class="com.fs.controller.UserController"> </bean>异常 获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常!NoSuchBeanDefinitionException。
2、demo测试。
- 如下。service注入controller层。
- UserService中的测试方法(main)使用ApplicationContext(IoC容器)管理bean、bean与bean之间的依赖关系。
package com.fs.controller; import com.fs.service.UserService; import org.springframework.context.support.ClassPathXmlApplicationContext; // UserController类 public class UserController { //service依赖注入 UserService userService; public void setUserService(UserService userService) { this.userService = userService; } //UserController类的print方法 public void print(){ System.out.println("UserController的print方法"); userService.print(); } //测试spring容器管理bean的main方法 public static void main(String[] args) { //创建容器 ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("springConfig.xml"); //通过spring工厂获取指定bean对象 UserController userController = app.getBean("userController", UserController.class); /*UserController userController = new UserController(); 取消这种手动new对象的操作*/ userController.print(); } }
package com.fs.service; // UserService类 public class UserService { //UserService类的成员方法 public void print(){ System.out.println("UserService的print方法"); } }
- 测试类(MainApp)。使用BeanFactory管理bean、bean与bean之间的依赖关系。
package com.fs; import com.fs.controller.UserController; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; public class MainApp { public static void main(String[] args) { //使用BeanFactory工厂实现IoC、DI(依赖注入与控制反转) //使用DefaultListableBeanFactory(BeanFactory的实现类) DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory(); //加载配置清单 XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory); xmlBeanDefinitionReader.loadBeanDefinitions("springConfig.xml"); Object obj = defaultListableBeanFactory.getBean("userController"); UserController userController = (UserController) obj; userController.print(); } }
- spring配置文件。(管理UserService、UserController类的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"> <!--配置生产UserService对象--> <bean id="userService" class="com.fs.service.UserService"></bean> <!--配置生产UserController对象--> <bean id="userController" class="com.fs.controller.UserController"> <!--配置属性值--> <property name="userService" ref="userService"></property> </bean> </beans>
运行结果。
使用别名。
<!--配置生产UserController对象--> <!--id只能有一个,name(别名)可以多个--> <bean id="userController" name="controller controller2" class="com.fs.controller.UserController"> <!--配置属性值--> <property name="userService" ref="userService"></property> </bean>
- 测试结果。
对应ref属性值最好使用id属性对应的值。但是也可以使用name属性对应的值!(ref:在依赖注入中使用到的)
3、NoSuchBeanDefinitionException!
- 表示在spring容器中未找到指定的Bean定义。这个异常在spring框架的学习或者实战中很常见!
- 以后一旦出现了就要查看:向spring容器getBean()获取对象时的参数bean的id或name属性是否写对?其次就是spring配置文件中的<bean>标签的id或name属性是否写对?
(3)bean作用范围配置。
1、基本介绍。
- 所谓的bean的作用范围(scope)——简单情况:当前spring容器创建的bean是单例的还是非单例。也就是一个对象还是多个对象。
- 可以通过scope属性来设置bean的作用域,它的取值有以下几个(基本介绍)。
类别 描述 名称 scope 类型 属性 所属 标签<bean>的基本属性 基本功能 定义bean的作用范围。其实是控制bean创建的实例的数量!
主要的范围可选如下:
- singleton:单例(默认)。每次调用getBean()都返回同一个bean对象。
- prototype:原型。每次从spring容器调用getBean()返回一个新的bean对象。相当于执行newXxxBean()。
- request与session仅适用于WebApplicationContext环境。
- request。(每次HTTP请求都会实例化一个新的bean)
- session。同一个HttpSession共享一个bean。不同HttpSession使用不同的bena。
- 等等。
示例 <bean id="userController" name="controller" class="com.fs.controller.UserController" scope="prototype"> </bean>
通过scope属性来设置bean的作用域,它的取值有以下几个(基本介绍)
2、demo测试。
- 改进一下上面的代码。getBean()获取对象后打印多次!查看其地址是否一致。
//测试spring容器管理bean的main方法 public static void main(String[] args) { //创建容器 ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("springConfig.xml"); //通过spring工厂获取指定bean对象 UserController userController = app.getBean("userController", UserController.class); UserController userController2 = app.getBean("userController", UserController.class); System.out.println(userController); System.out.println(userController2); }
测试结果如下。结论:spring容器默认生产的是单例的对象。(也就是是同一个对象)
为bean标签内添加属性"scope",并赋值"prototype"。(改成非单例)
3、为什么spring容器默认bean为singleton(单例)?
<1>基本解释。
- 对应spring容器,它帮程序员管理的bean对象需要放到容器中,如果不是单例的,那么它的容器里就需要装下无穷无尽的bean。(用一次造一次新的bean)这样spring容器会有很大的压力。
- 如果执行dao层方法需要造一个对象,下一次执行dao层方法又要造一次,可以想想这种情景下使用同一个bean对象也是同样可以满足的。
- 其实spring为我们管理的就是那些可以复用的对象。就是某个对象用一次,下一次还是从容器中拿取并用同样的它。这样的效率会提升很大!
<2>适合交给spring容器管理的bean。
- 表现层对象。(Servlet)
- 业务层对象。(service层)
- 数据层对象。(Dao、Mapper层)
- 工具类对象。
上面这些对象在实际开发中造一次就ok了,一直使用同一个对象即可完成操作。
<3>不适合交给容器进行管理的bean。
- 封装实体类对象。(比如某个对象封装的数据是1,下一次就可能封装的数据2,这种对象就不合适交给spring容器管理)
(4)bean其他属性配置(初始化、销毁等等)
- 使用<bean>标签内的属性:init-method="初始化方法"、destroy-method="销毁方法"。
- 详细的可能在后面的bean生命周期提到!
二、IoC与DI的入门案例。
- 简单使用spring完成IoC与DI的入门案例。
(1)demo的前提须知。
1、项目准备工作。
- 该工程有三个包:T包(测试包)、a包、b包。
- a包中有类"A",类"A"中有一个成员方法sum()。b包中有一个类"B",类"B"中有成员方法jisuan()。
2、项目要求。
- 要求:将类"A"与类"B"对象的实例化与对象间的依赖交给外部容器管理(spring管理)。也就是不能通过手动的new它们的对象就完成操作。
- 使用spring的核心思想(IoC、DI)完成该案例。涉及的两种spring容器(ApplicationContext容器、BeanFactory(Bean工厂))
3、spring提供的二种容器(实例化与管理bean)。
- spring容器是spring框架的核心。IoC容器具有依赖注入(DI)功能的容器。它可以创建对象,IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
- 通常new一个实例,控制权由程序员控制,而"IoC(控制反转)"是指new实例工作不由程序员来做而是交给Spring容器来做。
(2)pom文件引入(spring-context)坐标依赖。
- Maven本地仓库:https://mvnrepository.com/search?q=spring-context。
- 导入spring-context的坐标。
- 选择对应合适的版本。
- 复制依赖(spring-context)的坐标即可。
- pom.xml文件中引入依赖(spring-context)坐标。导入完记得刷新Maven。
(3)spring配置文件(配置相应bean)。
- 本项目的demo的配置文件:springBean.xml。
- 在resources目录下新建spring.xml(配置文件)。
- 注意:只有导入spring-context依赖的前提下,才会有这个"Spring 配置"的创建选项。
- 使用<bean>标签配置spring容器需要管理的bean(a包类"A"与b包类"B")。
<?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"> <!--配置生产a包下的A类对象--> <bean id="A" class="com.fs.a.A" scope="prototype"> <property name="b" ref="B"></property> </bean> <!--配置生产b包下的B类对象--> <bean id="B" class="com.fs.b.B"></bean> </beans>
(4)实体类"A"、实体类"B"。
1、ApplicationContext(IoC容器)。
在实体类"A"中的main()方法测试:使用spring的ApplicationContext容器的实现类"ClassPathXmlApplicationContext"类进行读取spring配置文件。通过getBean()方法获取类"A"对象的实例。
通过spring容器组件(对象)间的依赖管理(依赖注入DI)完成类"B"对象实例。
- spring配置文件中配置依赖关系。
- 在spring配置文件中的<bean>内部使用<property>标签指定:属性name(对应类"A"中的成员变量b(类"B"的对象))、属性ref(对应spring管理的类"B"的id(唯一标识))
- 因为类"A"中有一个类"B"的成员属性。还需要通过手动提供对应的setter方法完成类"B"的依赖注入。(需要注入的对象提供setter方法)
- spring的类"A"与类"B"的bean管理已经在spring配置文件中写好,并且之间的依赖管理也已标明。
package com.fs.a; import com.fs.b.B; import org.springframework.context.support.ClassPathXmlApplicationContext; //A类 public class A { //需要依赖注入的成员变量 B b; //提供对于需要依赖注入的成员变量b的setter方法 public void setB(B b) { this.b = b; } //A类的sum()方法 public void sum(){ System.out.println("A类的计算方法"); //通过类"A"的bean对象实例化时的依赖注入(DI)类"B"对象 //再调用B类的jisuan()方法 b.jisuan(); } //A类的mian()方法 public static void main(String[] args) { //使用IoC容器(ApplicationContext)获取spring容器管理的bean对象 //1.创建容器对象。实例化时参数指定对应的配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springBean.xml"); //2.通过<bean>标签的唯一标识id获取对应类"A"的实例对象 Object obj = context.getBean("A"); //3.强制类型转换 A a = (A)obj; //4.调用A类的sum()方法 a.sum(); } }
package com.fs.b; //类B public class B{ //B类的计算方法 public void jisuan(){ System.out.println("B类的计算方法"); } }
2、BeanFactory(Bean工厂)。
- 在T包的测试类中,第1步,使用BeanFactory的实现类"DefaultListableBeanFactory"来创建Bean工厂对象。
- 比起ApplicationContext的实现类"ClassPathXmlApplicationContext"容器拿取spring容器管理的bean对象需要多出一点步骤!
- 第2步。需要使用类"XmlBeanDefinitionReader"的对象获取读取配置文件的类,记得传入参数(上面创建的Bean工厂实现类的对象)。
- 第3步。调用loadBeanDefinitions()方法加载配置文件。方法内部参数:spring配置文件名。
- 第4步。通过getBean()方法获取spring管理的对象"A"。
- 使用spring的ApplicationContext容器管理类"A"对象的实例。通过spring容器组件(对象)间的依赖管理(依赖注入DI)完成类"B"对象实例。
package com.fs.T; import com.fs.a.A; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; //测试类 public class Main { public static void main(String[] args) { //使用bean工厂的实现类实例化对象 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //实例化类XmlBeanDefinitionReader(读取配置文件类) XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(factory); //加载配置文件 xmlBeanDefinitionReader.loadBeanDefinitions("springConfig.xml"); //也是通过<bean>标签的唯一标识id获取对应类"A"的实例对象 A a2 = (A)factory.getBean("A"); //调用A类的sum()方法 a2.sum(); } }
(5)运行结果。
- ApplicationContext(IoC容器)管理bean。
- BeanFactory(Bean工厂)管理bean。