目录
前言
第一种:静态工厂方式实例化对象
静态工厂的特点
demo(案例)
第二种:实例工厂的方式
实例工厂和静态工厂的区别
demo(案例)
第三种:实现FactoryBean规范的方式
demo(案例)
前言
spring 实例化对象的几种方式
- 使用 构造方法实例化对象 spring学习(spring-bean实例化(无参构造与有参构造方法实现)详解)-CSDN博客
- 工厂方式创建对象。
工厂方式实例化对象又可以分为三种情况:
一种是静态工厂;另一种是实例工厂;还有一种实现FactoryBean方式;下面我们就这三种方式分别实现一下。
准备工作 :导入 spring-context 依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
第一种:静态工厂方式实例化对象
静态工厂的特点
通过属性factory-method来指定一个静态方法,在该静态方法中达到创建对象的目标并返回交给spring容器管理。
demo(案例)
在 IDEA 新建两个类 学生 类,老师类,当前使用 静态工厂方式 创建 学生类对象
根据是否提前在 目标类 写静态方法 有两者写法
- 先在目标类中 写好 静态方法
spring 配置文件 中
Test 测试类
运行结果
注意:factory -method 属性值 是 你添加的静态方法名。如果你事先没有确定好静态方法,可以根据提示自定义方法名,创建在目标类中
- 先不在目标类中添加静态方法,而是在配置文件中 自定义 静态方法名,之后再目标类中完善方法
根据提示自定义方法名,自动创建在目标类中
重新运行结果是一样的
现在有一个问题 ,使用 学生类的静态方法,创建老师类对象 是否可行呢?
在 Test 测试类中
运行结果
发现,确实可以 创建 老师类对象。
在测试类,我想要获得是 学生类对象,但因为我在 学生类的添加的静态方法中,返回老师对象,最终结果打印的也是老师对象的地址。这个情况,我们常常戏称为 狸猫换太子
具体的底层代码细节如下
通过这个现象 思考几个问题
- 1 学生类对象 创建了没有
观察
1 spring 配置文件是否有表示学生信息的bean 标签
2 静态方法中是否有通过new 关键字创建对象
- 2 老师 类对象 有没有交给 spring 容器 管理
我认为 老师类 对象有spring 容器的参与,但实际上创建还是 new 出来的。
看下一个知识点: 实例化工厂 创建
总结 静态工厂 实例化对象
总结:采用静态工厂的方式去实例化对象,只需要在bean标签中指定一个静态方法即可,用factory-method属性来指定,方法名自已取,反正由idea自动帮我们创建好。然后我们只需要在创建好的静态方法中返回一个对象就搞定了。
第二种:实例工厂的方式
实例工厂和静态工厂的区别
- 实例工厂的方式,是在静态工厂的基础上在sping 配置文件 中 添加一个 factory-bean 属性,并实现真正目标类的方法
- 实例工厂创建对象 需要非静态方法,并且该方法是存在真正的创建对象的类中
demo(案例)
当前有 Ball ,Fruit 类 ,使用实例化工厂方式 创建 Ball 类对象
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">
<!--使用静态工厂创建对象-->
<bean id="student" class="fs.exerise01.Student" factory-method="getObject"/>
<!-- 实例工厂创建对象-->
<bean id="ball" class="fs.exerise02.Ball "></bean>
<bean id="fruit" class="fs.exerise02.Fruit" factory-method="getObject" factory-bean="ball"></bean>
</beans>
发现 factory-bean 的属性值 和 把目标对象交给 容器生产的 唯一标识符 id 的值是息息相关
从上面的图片可以知道:
是spring 容器通过构造方法创建 Ball 类对象,后对象调用在Ball 类的getObject 方法来创建真正需要的目标对象
Ball 类代码
package fs.exerise02;
public class Ball {
public Ball getObject() {
return new Ball();
}
}
Test测试类代码
package fs.exerise02;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Object bean = context.getBean("fruit");
System.out.println(bean);
}
}
运行结果
发现 表面上通过 getbean方法 获得 fruit 类对象方法,但实际是通过 实例化工厂方式创建ball类对象。真正做到了 移花接木的效果。
同样的道理,我们只需要修改Ball 类中的方法,可以任意创建目标对象?
如 之前在Ball 类中创建ball类对象。现在创建 fruit 类对象
其他的地方,一律不变!
运行结果
实例化工厂创建对象总结
1 使用实例化工厂创建对象,factory-bean 的属性值 表示真正调用本类的factory-method 属性值表示的方法
2 在本类方法中,我们可以修改方法,来实现任意对象的创建
第三种:实现FactoryBean规范的方式
demo(案例)
了解
Demo3 是 FactoryBean 接口的实现类,并重写 getObject 返回目标对象,getObjectType 返回 目标类的字节码文件,最终实现 Ball 类对象的创建
Demo3 类代码
package fs.exerise03;
import fs.exerise02.Ball;
import org.springframework.beans.factory.FactoryBean;
public class User implements FactoryBean<Ball> {
// 返回一个Ball对象
@Override
public Ball getObject() throws Exception {
return new Ball();
}
/// 返回Ball.class
@Override
public Class<?> getObjectType() {
return Ball.class;
}
}
Test 测试类
package fs.exerise03;
import fs.exerise02.Ball;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Ball demo3 = (Ball)context.getBean("user");
System.out.println(demo3.getObject());
}
}
运行结果