侧边栏壁纸
  • 累计撰写 101 篇文章
  • 累计创建 89 个标签
  • 累计收到 9 条评论

spring系列笔记 - 第⼋章 Spring工厂创建复杂对象(3种方式)

bearjun
2020-11-22 / 0 评论 / 0 点赞 / 1,511 阅读 / 4,887 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2020-11-22,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

20200522231012678.png

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:用于决定是否单例。

18275-cfsl23r8q2a.png

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的实现原理[简易版]**
本质:接口回调
问题:

  1. 为什么Spring规定FactoryBean接⼝实现并重写getObject()?
  2. 为什么applicationContext.getBean("conn")获得的是复杂对象Connection⽽非 ConnectionFactoryBean?

Spring 内部运行流程:
20200520004505899.png

  1. 调用applicationContext.getBean("conn"),根据配置文件中的id="conn"获得相关信息,从而通过instanceof判断出是否实现了FactoryBean接⼝;
  2. 如果实现了FactoryBean接口,spring就通过getObject()知道具体类型;
  3. 返回具体的复杂类型;

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⼯⼚创建对象的总结

50077-jl0zc9ffy6o.png

注意:上述图串联了前面的所有知识点,如果不清楚,请回去多看几遍,加深理解。

0

评论区