spring学习(spring-bean实例化(实现FactoryBean规范)(延迟实例化bean))
目录
一、spring容器实例化bean的几种方式。
(1)无参构造与有参构造方法。
(2)静态工厂与实例工厂。
(3)实现FactoryBean规范。
二、spring容器使用实现FactoryBean规范方式实现bean实例化。
(1)基本介绍。
(2)实现FactoryBean规范完成bean实例化的基本步骤。
1、测试项目准备工作。
2、指定工厂类中实现FactoryBean接口。
<1>方法getObject()。
<2>方法getObjectType()。
<3>方法isSingleton()。
3、spring配置文件中配置bean。(交给spring容器管理)
4、测试类。(MainApp)
(3)debug模式查看FactoryBean规范方式是延迟实例化bean。
1、设置断点。执行debug模式。
2、推进程序的执行,查看重要变量的赋值。
<1>属性beanFactory、beanDefinitionMap。
<2>属性singletonObjects。
<3>spring缓存机制。属性factoryBeanObjectCache。
-
本篇博客接着上篇《spring容器使用实例工厂实例化bean》继续学习。
一、spring容器实例化bean的几种方式。
(1)无参构造与有参构造方法。
- 使用构造方法实例化bean。spring学习(spring-bean实例化(无参构造与有参构造方法实现)详解)-CSDN博客
(2)静态工厂与实例工厂。
- 使用静态工厂方式实例化bean。spring学习(spring-bean实例化(静态工厂))-CSDN博客
- 使用实例工厂方式实例化bean。spring学习(spring-bean实例化(实例工厂))-CSDN博客
(3)实现FactoryBean规范。
- 最后一种实例化bean的方式:实现FactoryBean规范。(在本篇博客进行学习)
二、spring容器使用实现FactoryBean规范方式实现bean实例化。
- 实现FactoryBean规范涉及实现接口FactoryBean<泛型>。
(1)基本介绍。
- 在spring框架中,FactoryBean是一种特殊的bean,允许我们进行自定义实例化bean的过程。
- 通过实现FactoryBean<?>接口,可以控制spring容器完成创建和初始化bean。
(2)实现FactoryBean规范完成bean实例化的基本步骤。
1、测试项目准备工作。
- 本篇博客通过简单demo工程进行代码演示。
- 整体的项目结构。分为工厂包(factory)、业务层包(service)、测试包(test)。
- 目的:类"UserServiceFactoryBean"实现FactoryBean规范并为类"UserServiceImpl"实例化bean。
2、指定工厂类中实现FactoryBean<?>接口。
- 注:"<?>"表示需提供的泛型。(表示需要实例化bean的类型)
- 具体核心操作是实现该接口的两个方法。另外一个方法一般不实现。下面具体介绍!
<1>方法getObject()。
- 代替实例工厂提供的实例方法或者静态工厂提供的静态方法。
- 作用:返回<?>泛型指定类型的实例化bean。
<2>方法getObjectType()。
- 作用:返回创建的实例的类型(返回对应的字节码对象:xxx.class)。
<3>方法isSingleton()。
- 方法isSingleton()。作用:设置spring容器实例化的bean是单例还是非单例对象。
- 它是FactoryBean接口中的default方法。不强制要求实现类去实现。
- 在Java中default类型的方法是一种特殊的方法,它允许接口中包含具体的实现代码,这样实现该接口的类可以继承这些方法的实现,但也可以覆盖它们以提供自己的实现。
类"UserServiceFactoryBean"(实现FactoryBean的工厂)。
package com.fs.factory; import com.fs.service.UserService; import com.fs.service.impl.UserServiceImpl; import org.springframework.beans.factory.FactoryBean; //实现FactoryBean的UserService工厂 public class UserServiceFactoryBean implements FactoryBean<UserServiceImpl> { //代替原始实例工厂创建对象的实例方法 @Override public UserServiceImpl getObject() throws Exception { System.out.println("UserServiceFactoryBean已工作......"); //return——UserServiceImpl对象 return new UserServiceImpl(); } //返回创建的实例的类型(返回对应类型的字节码.class) @Override public Class<?> getObjectType() { return UserService.class; } //设置实例化的bean是否单例 @Override public boolean isSingleton() { return true; //若不想返回单例的bean就return false //return false; } }
3、spring配置文件中配置bean。(交给spring容器管理)
- 不像静态工厂或者实例工厂实例化bean时,需要在<bean>标签上使用属性"factory_bean"或"factory_method"指定工厂或者指定方法(静态/实例)。
- 实现FactoryBean规范在spring配置文件的操作比较简单。
- 只需要将实现FactoryBean<?>接口的类完成<bean>标签的基础配置即可(id与class)。
<?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"> <!--实现FactoryBean规范实例化bean--> <!--配置UserServiceFactoryBean——生产UserServiceImpl类的bean--> <bean id="userServiceFactoryBean" class="com.fs.factory.UserServiceFactoryBean"></bean> </beans>
4、测试类。(MainApp)
- 使用ApplicationContext容器加载配置文件,并通过容器对象getBean()指定实现FactoryBean接口的工厂类的id获取对应实例化(UserServiceImpl类)的bean。
package com.fs.test; import com.fs.service.impl.UserServiceImpl; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { //使用IoC容器(ApplicationContext)获取spring容器管理的bean对象 //1.创建容器对象。实例化时参数指定对应的配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springBean.xml"); //2.通过<bean>标签的唯一标识id获取对应在spring容器已经配置的bean对象(生产UserServiceImpl类的bean) Object obj = context.getBean("userServiceFactoryBean"); //3.强制类型转换 UserServiceImpl userService = (UserServiceImpl) obj; //4.调用UserService中的save方法 userService.save(); } }
- 程序测试运行结果。
(3)debug模式查看FactoryBean规范方式是延迟实例化bean。
1、设置断点。执行debug模式。
- 在测试类中设置合适的断点。查看程序运行的整个过程。
2、推进程序的执行,查看重要变量的赋值。
- 刚进入main()方法。
- 执行第1步。
<1>属性beanFactory、beanDefinitionMap。
<2>属性singletonObjects。
- 发现"userServiceFactoryBean"与存储在beanDefinitionMap中的地址不一样。
- 因为底层spring实例化bean时,解析完<bean>标签后存储在beanDefinitionMap里面的bean再以键名的方式遍历存储到singletonObjects中。
- 此时还是没有发现工厂帮我们返回的"UserServiceImpl"的bean。(延迟实例化bean)
<3>spring缓存机制。属性factoryBeanObjectCache。
- 此时还在第一步。
- 当getBean()方法未执行。说明ApplicationContext容器创建后,我们需要的实例化bean(UserServiceImpl)还未及时创建(延时实例bean)。
- 继续下一步。执行getBean()方法后。
- 此时缓存变量"factoryBeanObjectCache"已经有对应已经实例好的bean了。