Spring5应用之复杂对象创建

作者简介 :☕️大家好,我是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 表示每次请求都创建一个新对象
java 复制代码
public interface FactoryBean<T> {
    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

具体使用

  • 开发步骤
    • 实现FactoryBean
    • 编写配置文件
    • 编写测试代码
  • 注意点
    • 配置文件中属性指定的类型是FactoryBean接口的实现类 ,但通过id值获得的却是这个类所创建的复杂对象
    • 如果需要获取工厂对象,在id前面加上&即可,比如getBean("&bean")
    • 实际开发中需要根据对象特点决定是创建一个还是每次都创建一个对象 可以使用依赖注入将配置信息注入到ConnectionFactoryBean中去,方便进一步解耦
java 复制代码
public class ConnectionFactoryBean implements FactoryBean<Connection> {
   @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;
   }
}
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="conn" class="com.aomsir.basic.factorybean.ConnectionFactoryBean" />
</beans>
java 复制代码
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,以便使用工厂的特定方法来创建对象
java 复制代码
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;
    }
}
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="connFactory" class="com.aomsir.basic.factorybean.ConnectionFactory" />
    <bean id="conn" factory-bean="connFactory" factory-method="getConnection" />
</beans>
java 复制代码
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 ,这可能会导致一些冗余的配置。在这种情况下,考虑使用静态工厂方法可以更简化配置,提高配置的简洁性

具体使用

  • 开发步骤
    • 创建静态工厂
    • 编写配置文件
    • 编写测试代码
java 复制代码
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;
    }
}
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="conn" class="com.aomsir.basic.factorybean.StaticConnectionFactory" factory-method="getConnection"/>
</beans>
java 复制代码
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接口、自己创建的实例工厂,或者静态工厂方法。静态工厂方法通常是对实例工厂的一种更简化的方式。您的选择应该取决于业务需求的复杂性和具体情况的分析

参考文献

相关推荐
VX:Fegn08951 小时前
计算机毕业设计|基于ssm + vue超市管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
Mr.朱鹏3 小时前
Nginx路由转发案例实战
java·运维·spring boot·nginx·spring·intellij-idea·jetty
代码丰6 小时前
SpringAI+RAG向量库+知识图谱+多模型路由+Docker打造SmartHR智能招聘助手
人工智能·spring·知识图谱
Java天梯之路6 小时前
Spring Boot 钩子全集实战(七):BeanFactoryPostProcessor详解
java·spring boot·后端
wr2005146 小时前
第二次作业,渗透
java·后端·spring
短剑重铸之日6 小时前
《SpringCloud实用版》生产部署:Docker + Kubernetes + GraalVM 原生镜像 完整方案
后端·spring cloud·docker·kubernetes·graalvm
爬山算法7 小时前
Hibernate(67)如何在云环境中使用Hibernate?
java·后端·hibernate
女王大人万岁8 小时前
Go标准库 io与os库详解
服务器·开发语言·后端·golang
露天赏雪8 小时前
Java 高并发编程实战:从线程池到分布式锁,解决生产环境并发问题
java·开发语言·spring boot·分布式·后端·mysql
短剑重铸之日9 小时前
《SpringCloud实用版》 Seata 分布式事务实战:AT / TCC / Saga /XA
后端·spring·spring cloud·seata·分布式事务