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接口、自己创建的实例工厂,或者静态工厂方法。静态工厂方法通常是对实例工厂的一种更简化的方式。您的选择应该取决于业务需求的复杂性和具体情况的分析

参考文献

相关推荐
假装我不帅1 小时前
asp.net framework从webform开始创建mvc项目
后端·asp.net·mvc
神仙别闹1 小时前
基于ASP.NET+SQL Server实现简单小说网站(包括PC版本和移动版本)
后端·asp.net
计算机-秋大田2 小时前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue
货拉拉技术2 小时前
货拉拉-实时对账系统(算盘平台)
后端
掘金酱3 小时前
✍【瓜分额外奖金】11月金石计划附加挑战赛-活动命题发布
人工智能·后端
代码之光_19803 小时前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi3 小时前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
鹿屿二向箔3 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架的咖啡馆管理系统
spring·mvc·mybatis
颜淡慕潇4 小时前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决