目录
一、配置文件(XML)中定义与配置bean。
(1)bean的基础配置。(id、class)
(2)bean的别名配置。
1、基本介绍。
2、demo测试。
3、NoSuchBeanDefinitionException!
(3)bean作用范围配置。
1、基本介绍。
2、demo测试。
spring%E5%AE%B9%E5%99%A8%E9%BB%98%E8%AE%A4bean%E4%B8%BAsingleton%EF%BC%88%E5%8D%95%E4%BE%8B%EF%BC%89%EF%BC%9F-toc" style="margin-left:160px;">3、为什么spring容器默认bean为singleton(单例)?
<1>基本解释。
spring%E5%AE%B9%E5%99%A8%E7%AE%A1%E7%90%86%E7%9A%84bean%E3%80%82-toc" style="margin-left:200px;"><2>适合交给spring容器管理的bean。
<3>不适合交给容器进行管理的bean。
(4)bean其他属性配置(初始化、销毁等等)
IoC%E4%B8%8EDI%E7%9A%84%E5%85%A5%E9%97%A8%E6%A1%88%E4%BE%8B%E3%80%82-toc" style="margin-left:80px;">二、IoC与DI的入门案例。
(1)demo的前提须知。
1、项目准备工作。
2、项目要求。
spring%E6%8F%90%E4%BE%9B%E7%9A%84%E4%BA%8C%E7%A7%8D%E5%AE%B9%E5%99%A8%EF%BC%88%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%8E%E7%AE%A1%E7%90%86bean%EF%BC%89%E3%80%82-toc" style="margin-left:160px;">3、spring提供的二种容器(实例化与管理bean)。
spring-context)%E5%9D%90%E6%A0%87%E4%BE%9D%E8%B5%96%E3%80%82-toc" style="margin-left:120px;">(2)pom文件引入(spring-context)坐标依赖。
spring%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%88%E9%85%8D%E7%BD%AE%E7%9B%B8%E5%BA%94bean%EF%BC%89%E3%80%82-toc" style="margin-left:120px;">(3)spring配置文件(配置相应bean)。
(4)实体类"A"、实体类"B"。
IoC%E5%AE%B9%E5%99%A8%EF%BC%89%E3%80%82-toc" style="margin-left:160px;">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"。(改成非单例)
spring%E5%AE%B9%E5%99%A8%E9%BB%98%E8%AE%A4bean%E4%B8%BAsingleton%EF%BC%88%E5%8D%95%E4%BE%8B%EF%BC%89%EF%BC%9F" style="background-color:transparent;">3、为什么spring容器默认bean为singleton(单例)?
<1>基本解释。
- 对应spring容器,它帮程序员管理的bean对象需要放到容器中,如果不是单例的,那么它的容器里就需要装下无穷无尽的bean。(用一次造一次新的bean)这样spring容器会有很大的压力。
- 如果执行dao层方法需要造一个对象,下一次执行dao层方法又要造一次,可以想想这种情景下使用同一个bean对象也是同样可以满足的。
- 其实spring为我们管理的就是那些可以复用的对象。就是某个对象用一次,下一次还是从容器中拿取并用同样的它。这样的效率会提升很大!
spring%E5%AE%B9%E5%99%A8%E7%AE%A1%E7%90%86%E7%9A%84bean%E3%80%82"><2>适合交给spring容器管理的bean。
- 表现层对象。(Servlet)
- 业务层对象。(service层)
- 数据层对象。(Dao、Mapper层)
- 工具类对象。
上面这些对象在实际开发中造一次就ok了,一直使用同一个对象即可完成操作。
<3>不适合交给容器进行管理的bean。
- 封装实体类对象。(比如某个对象封装的数据是1,下一次就可能封装的数据2,这种对象就不合适交给spring容器管理)
(4)bean其他属性配置(初始化、销毁等等)
- 使用<bean>标签内的属性:init-method="初始化方法"、destroy-method="销毁方法"。
- 详细的可能在后面的bean生命周期提到!
IoC%E4%B8%8EDI%E7%9A%84%E5%85%A5%E9%97%A8%E6%A1%88%E4%BE%8B%E3%80%82" style="background-color:transparent;">二、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工厂))
spring%E6%8F%90%E4%BE%9B%E7%9A%84%E4%BA%8C%E7%A7%8D%E5%AE%B9%E5%99%A8%EF%BC%88%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%8E%E7%AE%A1%E7%90%86bean%EF%BC%89%E3%80%82" style="background-color:transparent;">3、spring提供的二种容器(实例化与管理bean)。
- spring容器是spring框架的核心。IoC容器具有依赖注入(DI)功能的容器。它可以创建对象,IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
- 通常new一个实例,控制权由程序员控制,而"IoC(控制反转)"是指new实例工作不由程序员来做而是交给Spring容器来做。
spring-context)%E5%9D%90%E6%A0%87%E4%BE%9D%E8%B5%96%E3%80%82" style="background-color:transparent;">(2)pom文件引入(spring-context)坐标依赖。
- 选择对应合适的版本。
- 复制依赖(spring-context)的坐标即可。
spring%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%EF%BC%88%E9%85%8D%E7%BD%AE%E7%9B%B8%E5%BA%94bean%EF%BC%89%E3%80%82" style="background-color:transparent;">(3)spring配置文件(配置相应bean)。
- 注意:只有导入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"。
IoC%E5%AE%B9%E5%99%A8%EF%BC%89%E3%80%82" style="background-color:transparent;">1、ApplicationContext(IoC容器)。
在实体类"A"中的main()方法测试:使用spring的ApplicationContext容器的实现类"ClassPathXmlApplicationContext"类进行读取spring配置文件。通过getBean()方法获取类"A"对象的实例。
- 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"。
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。