Spring工厂创建复杂对象

时间:2022-07-24
本文章向大家介绍Spring工厂创建复杂对象,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

什么是复杂对象

复杂对象是指无法使用 new 关键字直接创建的对象,比如在使用数据库连接的时候,我们需要用如下的方式创建对象:

Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useSSL=false", "root", "root");

再比如在使用 MyBatis 时要获取 SQLSessionFactory 也是不能使用 new 直接创建的。

Spring 工厂创建复杂对象的3种方式

1. FactoryBean 接口

Spring为我们提供了一个 FactoryBean 接口,我们可以实现该接口,并重写方法来创建复杂对象。

public class MyFactoryBean implements FactoryBean<Connection> {
    
    // 用于书写创建复杂对象
    @Override
    public Connection getObject() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useSSL=false", "root", "root");
    }

    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

	// 是否单例
    @Override
    public boolean isSingleton() {
        return false;
    }
}

同时我们需要将该类加入到 Spring 容器中。

<bean class="edu.lsu.factorybean.MyFactoryBean" id="conn"/>

如果 class 中指定的类型是 FactoryBean 接口的实现类,那么通过 id 值获取的是这个类所创建的复杂对象。

ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
Connection conn = ac.getBean("conn", Connection.class);
System.out.println("conn = " + conn);

输出:
conn = com.mysql.jdbc.JDBC4Connection@4c40b76e

如果我们就像获取 FactoryBean 类型的变量,可以这样写:

ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
MyFactoryBean acBean = ac.getBean("&conn", MyFactoryBean.class);
System.out.println("acBean = " + acBean);

输出:
acBean = edu.lsu.factorybean.MyFactoryBean@5fcd892a

在 id 前面加上一个 & 号。

如果我们设置 isSingleton 的返回值为 true,那么多次获取的对象都是同一个,如果返回 false 则每次都会创建一个新的对象。

那么为什么 Spring 要定一个 FactoryBean 接口呢?

  • 正如一句谚语所说:“接口加反射,什么都能做。” FactoryBean 接口就是一个接口回调。

FactoryBean 的工作原理:

  • Spring 首先从配置文件中通过 conn 获取 bean 对象,然后判断 instance(FactoryBean) 子类。
  • 调用 getObject() 方法,创建复杂对象。

2. 实例工厂

由于实现 FactoryBean 接口会引起 Spring 框架的侵入,即一旦我们离开了 Spring,那么代码将不能使用。

至于为什么叫做实例工厂是因为只有再创建实例之后才能调用它的方法。

public class ConnectionFactory {
    public Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&amp;useSSL=false", "root", "root");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

同时需要在配置文件中配置如下信息:

<bean class="edu.lsu.factorybean.ConnectionFactory" id="connectionFactory"/>
<bean id="connection" factory-bean="connectionFactory" factory-method="getConnection"/>

3. 静态工厂

静态工厂和实例工厂的区别就在于实例工厂的方法是实例方法,而静态工厂的方法是静态的。

public class StaticConnectionFactory {
    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&amp&useSSL=false", "root", "root");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

在配置文件上略有区别:

<bean class="edu.lsu.factorybean.StaticConnectionFactory" id="staticConnectionFactory" factory-method="getConnection"/>

静态工厂不需要创建对象就能调用方法,所以直接使用标签的属性即可。