Spring学习笔记07 - Spring创建复杂对象以及FactoryBean实现原理

复杂对象

什么是复杂对象?
简单对象:指可以直接通过new 构造方法创建的对象。
(反射的底层也是new)
复杂对象:指不能通过new构造方法创建的对象。

  • Connection
  • SqlSessionFactory
    。

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

1. FactoryBean 接口

开发步骤:

  • 实现FactoryBean接口
  • Spring配置文件的配置

实现FactoryBean接口

FactoryBean 接口里 有三个方法 需要实现

  1. getObject - 在里面写创建复杂对象的代码,并返回创建的 复杂对象
  2. getObjectType - 返回 所创建复杂对象的Class对象
  3. isSingleton - 返回boolean值。需要创建一次 - 返回true,每一次调用都创建一个复杂对象 - 返回false
package com.youcan.facotrybean;

import org.springframework.beans.factory.FactoryBean;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionFactoryBean implements FactoryBean<Connection> {
    @Override
    public Connection getObject() throws Exception {
    //用于书写创建复杂对象的代码,并把复杂对象作为方法的返回值 返回
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc://localhost:3306/adam","root", "mysql666");
        return conn;
    }
    @Override
    public Class<?> getObjectType() {
    //返回 所创建复杂对象的Class对象
        return Connection.class;
    }
	// 设置true:只需要创建一次 ,设置false: 每一次调用都创建一个复杂对象
    @Override
    public boolean isSingleton() {
        return false;
    }
}

在这里插入图片描述

Spring配置文件的配置

注意下返回值类型 (对比简单对象和复杂对象)

//复杂对象,通过FactoryBean接口的实现类ConnectionFactoryBean创建
<bean id="conn" class="com.youcan.factorybean.ConnectionFactoryBean">
//简单对象,通过Person直接创建
<bean id="person" class="com.gogogo.Person">

{这个地方 书写和 创建简单对象的书写格式是一样的
获得简单对象: ctx.getBean("person")获得的是 Person类的一个对象。}

在这里插入图片描述

注意:我们不一样

FactoryBean 接口实现类是ConnectionFactoryBean ,通过ctx.getBean("conn") 获得的是它所创建的复杂对象 Connection
(创建ConnectionFactoryBean这个类是为了得到 Connection对象,所以‘ConnectionFactoryBean这个类的对象 显得并不重要‘。返回值不是ConnectionFactoryBean这个类的对象。所以Spring对FactoryBean接口的实现类的返回指 做出了改变。)

ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Connection conn = (Connection) ctx.getBean("conn");
System.out.println("conn = " + conn);
//output
// conn = com.mysql.jdbc.JDBC4Connection@6329d432

在这里插入图片描述
小结
如果Class中指定的类型是FactoryBean接口的实现类,那么通过id值获得的是这个类所创建的复杂对象,即返回值是复杂对象。

Notice here

  1. 那么就行获得ConnectionFactoryBean对象,怎么做呢?
    ctx.getBean("&conn") 加 & 符号,
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
ConnectionFactoryBean conn = (ConnectionFactoryBean) ctx.getBean("&conn");
System.out.println("conn = " + conn);
//output
// conn = com.youcan.factorybean.ConnectionFactoryBean@9529a423
  1. isSingleton 方法
    返回true, 只会创建一个对象
    返回false,每次都会创建新的对象
    问题:根据这个对象的特点,决定是返回true 或者false。
    return true SqlSessionFactory对象, 只创建一次就可以。
    return false Connection对象,不可公用,每次都需要重建。
  2. mysql 高版本连接创建是,需要指定SSL证书,解决问题的方式:
    url = "jdbc:mysql://localhost:3306/adam?useSSL=false"
  3. 依赖注入的体会(DI)
    上一节有讲了,A依赖B,就可以把B作为成员变量,注入,解藕。
    即将ConnectionFactoryBean中依赖的4个字符串,进行配置文件注入,步骤如下:
    在这里插入图片描述
    修改完如下:
package com.youcan.factorybean;

import org.springframework.beans.factory.FactoryBean;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionFactoryBean implements FactoryBean<Connection> {
    private String driverClassName;
    private String url;
    private String user;
    private String password;
    //get set methods below

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    //用于书写创建复杂对象的代码, 即:连接对象
    @Override
    public Connection getObject() throws Exception {
        Class.forName(driverClassName);
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }
    //返回连接对象的class
    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }
    //设置成true,只创建一次
    @Override
    public boolean isSingleton() {
        return false;
    }
}

配置文件中:

<bean id="conn" class="com.youcan.factorybean.ConnectionFactoryBean">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/adam?userSSl=false"/>
    <property name="user" value="root"/>
    <property name="password" value="123456"/>
</bean>

FactoryBean 的实现原理(简易版)

  • 接口回调
  1. 为什么Spring规定FactoryBean接口,要把创建复杂对象的代码写在 getObject() 那个函数里?
  2. ctx.getbean("conn") 获得是复杂对象 Connection 而没有获得 ConnectionFactoryBean
  • Spring 内部运行流程
  1. 通过conn 获得 ConnectionFactoryBean类的对象,进而通过instanceof 判断出FactoryBean接口的实现类
  2. Spring按照规定 getObjectConnection
  3. 返回Connection
    在这里插入图片描述
  • FactoryBean总结
    Spring中用于创建复杂对象的一种方式,也是Spring原生提供的。

2. 实例工厂

为什么要用实例工厂?

  1. 避免Spring框架的侵入
  2. 整合遗留问题

开发步骤
当无法直接获得工厂代码时,我们可以通过创建实例工厂来获得功能。
factory-bean="connFactory" factory-method="getConnection"

package com.youcan.factorybean;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionFactory {
    public Connection getConnection(){
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/adam?userSSL=false", "root", "123456");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }
}

创建工厂对象 connFactory

  1. 先创建connFactory实例工厂
  2. 再来调用getConnection方法
<bean id="connFactory" class="com.youcan.factorybean.ConnectionFactory"></bean>
<bean id="conn" factory-bean="connFactory" factory-method="getConnection"></bean>

测试实例工厂结果:
创建连接对象 conn 调用connFactory工厂里的 getConnection 方法

public void Test5(){
     //获取工厂
     ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
     Connection conn = (Connection) ctx.getBean("conn");
     System.out.println(conn);
 }

3. 静态工厂

static主要体现在方法是static
在调用方法时可以直接使用
StaticConnectionFactory.getConnection()
(与实例工厂调用的区别)
配置文件:

//静态,创建对象,类名,方法
<bean id="conn" class="com.youcan.factorybean.StaticConnectionFactory" factory-method="getConnection"></bean>

spring 工厂创建对象的总结

在这里插入图片描述

学习快乐❤️
加加油~
“An essential part of creativity is not being afraid to fail.”
– Edwin H. Land

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值