1. 什么是复杂对象
简单对象:指的是可以直接通过new(构造方法)创建对象
例如: UserService 、UserDAO 、Customer.......
复杂对象:指的是不可以直接通过new构造方法创建的对象(Connection SqlSessionFactory)
例如:Connection 、SqlSessionFactory.......
2. Spring⼯⼚创建复杂对象的3种⽅式
2.1 FactoryBean接口
开发步骤:
1、实现FactoryBean接口:实现getObject,getObjectType,isSingleton方法;
1、getObject():用于书写创建复杂对象时的代码。
2、getObjectType():返回创建的复杂对象的类型。
3、isSingleton:用于决定是否单例。
public class ConnectionFactoryBean implements FactoryBean<Connection> {
// 用于书写创建复杂对象时的代码
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring", "root", "1234");
return conn;
}
// 返回创建的复杂对象的类型
@Override
public Class<Connection> getObjectType() {
return Connection.class;
}
// 是否单例
// return false; 每一次都创建新的复杂对象
// return true; 只创建一次这种类型的复杂对象
@Override
public boolean isSingleton() {
return false;
}
}
2、Spring 配置文件的配置
<!--简单的对象-->
<bean id="user" class="com.bearjun.entity.User"></bean>
<!--实现了factoryBean的复杂对象-->
<bean id="conn" class="com.bearjun.factorybean.MyFactoryBean"></bean>
注意:
如果配置的是简单的对象,通过applicationContext.getBean("user")获取到的是user对象
如果是实现了FactoryBean接⼝的复杂对象,那么通过applicationContext.getBean("conn")获得的是这个类所创建的复杂对象,也就是getObjectType()返回的那个类型的对象。比如上面class指定的是ConnectionFactoryBean,获得的这是Connection对象。
FactoryBean开发细节
- 如果就想要获得FactoryBean对象怎么办
可以通过applicationContext.getBean("&conn")获得的就是FactoryBean对象,注意是获取的**&+名称**。
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
ConnectionFactoryBean conn = (ConnectionFactoryBean) ctx.getBean("&conn");
- isSingleton()方法
返回true只会创建⼀个复杂对象,返回false每⼀次都会创建新的对象;
需要根据这个对象的特点,决定是返回true(SqlSessionFactory)还是false(Connection
);
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
ConnectionFactoryBean conn1 = (ConnectionFactoryBean) ctx.getBean("conn");
ConnectionFactoryBean conn2 = (ConnectionFactoryBean) ctx.getBean("conn");
System.out.println(conn1);
System.out.println(conn2);
// 若果返回false conn1 != conn2
// 若果返回true conn1 == conn2
- mysql⾼版本连接创建时,需要指定SSL证书,否则会警告;
## 解决方案:
url = "jdbc:mysql://localhost:3306/spring?useSSL=false"
- 依赖注入(DI)
把ConnectionFactoryBean中依赖的4个字符串信息,通过配置⽂件进行注⼊。
public class ConnectionFactoryBean implements FactoryBean<Connection> {
// 将依赖的字符串信息变为成员变量, 利用配置文件进行注入。
private String driverClassName;
private String url;
private String username;
private String password;
// 省略get/set方法
@Override
public Connection getObject() throws Exception {
Class.forName(driverClassName);
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
@Override
public Class<Connection> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
<bean id="conn" class="com.bearjun.factorybean.MyFactoryBean">
<property name="className" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mysql"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
** FactoryBean的实现原理[简易版]**
本质:接口回调
问题:
- 为什么Spring规定FactoryBean接⼝实现并重写getObject()?
- 为什么applicationContext.getBean("conn")获得的是复杂对象Connection⽽非 ConnectionFactoryBean?
Spring 内部运行流程:
- 调用applicationContext.getBean("conn"),根据配置文件中的id="conn"获得相关信息,从而通过instanceof判断出是否实现了FactoryBean接⼝;
- 如果实现了FactoryBean接口,spring就通过getObject()知道具体类型;
- 返回具体的复杂类型;
FactoryBean总结:
FactoryBean是Spring用于创建复杂类型对象的一种方式,也是Spring原生提供的,Spring在整合其他框架时会大量使用FactoryBean
2.2 实例工厂创建复杂对象
- 避免Spring框架的侵入(就是不用spring,现在根本就不可能)
- 整合遗留系统
历史遗留系统已经存在的:
public class FactoryBean {
public Connection getConnection(){
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql", "root", "root");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}
<!--实例工厂-->
<!-- 先创建出工厂实例 -->
<bean id="connFactory" class="com.bearjun.factorybean.ConnectionFactory"/>
<!-- 通过工厂实例里的方法创建复杂对象 -->
<bean id="conn" factory-bean="connFactory" factory-method="getConnection"/>
2.3 静态工厂
public class StaticFactoryBean {
// 静态方法
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring?useSSL=false", "root", "1234");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
}
<bean id="conn2" class="com.bearjun.factorybean.StaticFactoryBean" factory-method="getConnection"></bean>
3. Spring⼯⼚创建对象的总结
注意:上述图串联了前面的所有知识点,如果不清楚,请回去多看几遍,加深理解。
评论区