作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者!
个人主页:Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏
当前专栏:Spring5应用专栏_Aomsir的博客
什么是复杂对象?
讨论什么是复杂对象前,先讨论什么是简单对象,简单对象就是可以直接通过new的方式进行创建的对象。所以不能够通过new创建的对象就是复杂对象,如下图所示。当然,Spring也提供了几种不同的创建复杂对象的方式:FactoryBean接口
、实例工厂
、静态工厂
FactoryBean接口
FactoryBean
是Spring原生提供的创建复杂对象的方式,是Spring非常重要的一种机制,值的好好学习
接口原型
如下是FactoryBean
的接口原型,中有3个方法
- getObject()方法方法是用于书写创建复杂对象的代码,并将创建的对象作为方法的返回值进行返回,比如
Connection 对象
、SqlSessionFactory 对象
等 - getObjectType()方法是用于返回所创建复杂对象的具体类(Class)对象,以便 Spring 容器了解创建的对象的类型
- isSingleton()方法是用于确定是否创建单例对象,返回 true 表示创建单例对象,即在应用程序生命周期内只创建一个实例,而返回 false 表示每次请求都创建一个新对象
public interface FactoryBean {
@Nullable
T getObject() throws Exception;
@Nullable
Class getObjectType();
default boolean isSingleton() {
return true;
}
}
具体使用
- 开发步骤
- 实现FactoryBean
- 编写配置文件
- 编写测试代码
- 注意点
- 配置文件中属性指定的类型是FactoryBean接口的实现类,但通过id值获得的却是这个类所创建的复杂对象
- 如果需要获取工厂对象,在id前面加上&即可,比如getBean("&bean")
- 实际开发中需要根据对象特点决定是创建一个还是每次都创建一个对象 可以使用依赖注入将配置信息注入到ConnectionFactoryBean中去,方便进一步解耦
public class ConnectionFactoryBean implements FactoryBean {
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3307/demo", "root", "123456");
}
@Override
public Class getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
public class TestSpring {
@Test
public void test7() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取复杂对象
Connection conn = (Connection) ctx.getBean("conn");
// 获取FactoryBean对象
ConnectionFactoryBean connectionFactoryBean = (ConnectionFactoryBean) ctx.getBean("&conn");
System.out.println("conn = " + conn);
System.out.println("connectionFactoryBean = " + connectionFactoryBean);
}
}
实例工厂
- 使用实例工厂的原因:
- 避免Spring框架的侵入:使用FactoryBean接口需要引入Spring,如果后续项目不使用Spring了呢?
- 为了整合遗留系统:老系统已经提供好了工厂,没有实现Spring接口且只给了jar,该如何做?
- 这时候我们就可以考虑使用实例工厂
具体使用
- 开发步骤
- 创建实例工厂
- 编写配置文件
- 编写测试代码
- 注意
- 需要将实例工厂注入到Spring容器中,然后配置复杂对象的Bean,以便使用工厂的特定方法来创建对象
public class ConnectionFactory {
public Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3307/demo", "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
public class TestSpring {
@Test
public void test8() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Connection conn = (Connection) ctx.getBean("conn");
System.out.println("conn = " + conn);
}
}
静态工厂方法
在上述示例工厂中,需要配置两个Bean,这可能会导致一些冗余的配置。在这种情况下,考虑使用静态工厂方法可以更简化配置,提高配置的简洁性
具体使用
- 开发步骤
- 创建静态工厂
- 编写配置文件
- 编写测试代码
public class StaticConnectionFactory {
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3307/demo", "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
public class TestSpring {
@Test
public void test9() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Connection conn = (Connection) ctx.getBean("conn");
System.out.println("conn = " + conn);
}
}
总结
在处理复杂对象的依赖注入时,您可以根据业务需求选择使用Spring提供的FactoryBean接口
、自己创建的实例工厂
,或者静态工厂方法
。静态工厂方法通常是对实例工厂的一种更简化的方式。您的选择应该取决于业务需求的复杂性和具体情况的分析
参考文献
- 孙哥suns说Spring5~学不会Spring? 因为你没找对人
- Spring官方文档