Spring工厂创建对象分析
文章目录
1. 创建简单对象
1.1 什么是简单对象?
简单对象指的就是可以通过new的方式就创建出的对象。
只要写好相关配置文件,简单对象就可以通过Spring工厂创建。
1.2 创建简单对象的方式
-
创建类文件
-
编写配置文件
<bean id="user" class="com.jc.bean.User" p:id="1" p:username="Tom"/>
2. 创建复杂对象
2.1 什么是复杂对象?
复杂对象:指的就是不能直接通过new构造方法创建的对象
例如:连接数据库所需要的Connection
对象,需要创建它就需要先创建另一个对象并且经过一些操作才能获取。类似的还有Mybatis中的SqlSessionFactory
。
2.2 创建复杂对象的3种方式
2.2.1 FactoryBean接口
① 开发步骤
- 实现FactoryBean接口:
package com.jc.factory;
import org.springframework.beans.factory.FactoryBean;
import java.sql.Connection;
import java.sql.DriverManager;
public class MyFactoryBean implements FactoryBean<Connection> {
/**
* 用于获取复杂对象
* @return
* @throws Exception
*/
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "root", "123456");
return connection;
}
/**
* 用于返回创建的复杂对象的类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Connection.class;
}
/**
* 返回是否为单例
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
}
- 编写Spring配置文件
# 如果Class中指定的类型是FactoryBean接⼝的实现类,那么通过id值获得的是这个类所创建的复杂对象:Connection <bean id="conn" class="com.jc.factorybean.MyFactoryBean"/>
-
细节分析
- 如果就想获得FactoryBean类型的对象 加上"&",如:
ctx.getBean("&conn")
获得就是ConnectionFactoryBean对象 - isSingleton()方法返回 true 只会创建⼀个复杂对象,返回 false 每一次都会创建新的对象 问题:根据这个对象的特点 ,决定是返回true还是 false(例如SqlSessionFactory这样占用资源多的对象适合用true,Connection对象这种对象适合false)
- 如果就想获得FactoryBean类型的对象 加上"&",如:
-
体会依赖注入的使用
将连接信息都作为成员变量,之后在Spring配置文件中指定值
public class MyFactoryBean implements FactoryBean<Connection> {
private String url;
private String username;
private String password;
// set、get方法,构造器...
// 实现接口的方法...
}
Spring配置文件:
<bean id="conn" class="com.jc.factory.MyFactoryBean">
<property name="url" value="jdbc:mysql://localhost:3306/demo?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
② FactoryBean原理简易分析
FactoryBean的实现本质上就是接口回调。
什么是接口回调?
接口回调简单来讲就是别人调用你定义的方法。比如有一个接口A,它的实现是AImpl;同时还有一个类B,B中有接口A类型的引用,B调用完A中定义的方法后,会通过这个引用告诉接口A调用的结果,告诉A执行完了这个方法。但是因为A是一个接口,所以接收结果的逻辑有A的实现类来处理。
就像FactoryBean一样:
我们通过ApplicationContext中的方法getBean()
获取数据库连接对象Connection
,而实际创建Connection
的任务是由我们重写的FactornBean中的getObject()
方法来实现的。
2.3 实例工厂
实例工厂的作用:
- 防止Spring的侵入
- 整合遗留系统
如果有以前版本的代码,我们要使用,并且不能对前的代码进行修整,就可以考虑使用实例工厂。
实例工厂如其名,我们想要使用一个类中的方法,就需要在Spring配置文件中配置类的实例信息,将其注入。
使用步骤:
1.将需要用到的类编写在配置文件中
2.引入factory-bean
标签
配置举例:
假设这是无法修整的代码:此方法用于获取数据库连接
public class ConnFactory {
public Connection getConnection() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}
Spring配置文件:
<bean id="myFactoryBean" class="com.jc.factory.ConnFactory" ></bean>
<bean id="conn" factory-bean="myFactoryBean" factory-method="getConnection"/>
2.4 静态工厂
与实例工厂类似,不同是我们不需要在配置文件中编写提供实例的配置,因为实现功能的是静态方法。
代码举例:
public class StaticConnFactory {
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}
Spring配置文件:
<bean id="conn" class="com.jc.factory.StaticConnFactory" factory-method="getConnection"/>
3. 总结
对于简单类型的对象,我们只需要编辑配置文件,之后Spring会进行注入,而创建复杂类型的对象,就需要通过实现FactoryBean接口的方式。但是想要用Spring工厂创建对象,就一定要将对象的信息配置到Spring配置文件中。对于遗留系统,我们需要获取其中的实例,建议使用实例工厂或是静态工厂的方式。