Spring 从入门到精通 (十) 复杂对象详解

举报
周棋洛 发表于 2022/07/22 00:56:33 2022/07/22
【摘要】 关键词:Spring | 复杂对象 本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨ 目录 一、什么是简单对象?...

关键词:Spring | 复杂对象

本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨

在这里插入图片描述

一、什么是简单对象?

可以直接 new 构造方法来创建的对象,就是简单对象,反射底层一样会调用构造方法

二、什么是复杂对象?

不能直接通过 new 构造方法创建的对象

举例:常见的 jdbc 中的 Connection 对象,mybatis 中的 SqlSessionFactory 对象

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

  • FactoryBean接口
  • 实例工厂
  • 静态工厂

3.1、FactoryBean接口

现在想把 jdbc 中的 Connection 对象也交给 Spring 创建

首先,在 pom 中引入 MySQL 驱动 jar 包

<!--MySQL驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
</dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

开发自己的 FactoryBean

package factorybean;


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:mysql://localhost:3306/zhou", "root", "root");
        return conn;
    }

    // 返回创建对象的Class对象
    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

spring配置文件

<!--如果Class中指定的类型是FactoryBean接口的实现类
那么通过id获得的是这个类创建的复杂对象 Connection-->
<bean id="conn" class="factorybean.ConnectionFactoryBean"/>

  
 
  • 1
  • 2
  • 3

测试

@Test
public void t3() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
    Connection conn = (Connection) context.getBean("conn");
    System.out.println(conn);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
com.mysql.jdbc.JDBC4Connection@591ac8

  
 
  • 1

3.1.1、FactoryBean细节1

如果我们在获取是,在 id 前加上“&”符号,那么获取的将不再是复杂对象,而是 ConnectionFactoryBean 对象

@Test
public void t4() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
    ConnectionFactoryBean conn = (ConnectionFactoryBean) context.getBean("&conn");
    System.out.println(conn);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
factorybean.ConnectionFactoryBean@18edcc5

  
 
  • 1

3.1.2、单例还是多例?

如果对象能够被公用,就设置为单例,即返回 true ,否则设置为多例,返回false,jdbc 的 Connection 对象在事务处理时,明显不可以公用,因此使用多例比较合适,而 MyBatis 的 SqlSessionFactory 是重量级的对象,因此使用单例更为合适,其他对象可以根据上述原则配置即可。

3.1.3、SSL证书错误处理

由于mysql版本问题,你可能会遇到报错说没有使用ssl证书,因为mysql为了保证更加安全,添加了ssl证书验证,当然我们是没有的哈,只需要在url上配置一下就不在提示了。

useSSL=false

  
 
  • 1
jdbc:mysql://localhost:3306/zhou?useSSL=false

  
 
  • 1

3.1.4、耦合优化

ConnectionFactoryBean中用户名,密码,url等等参数直接通过字符串的形式写在了程序里,使用了硬编码,耦合了,我们使用依赖注入来解决这块的耦合。

依赖这几个字符串,就把他们声明为成员变量,并提供set方法

package 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 username;
    private String password;

    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 getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

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

    // 写创建复杂对象的代码
    @Override
    public Connection getObject() throws Exception {
        Class.forName(driverClassName);
        return DriverManager.getConnection(url, username, password);
    }

    // 返回创建对象的Class对象
    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

在Spring配置文件中完成注入

<bean id="conn" class="factorybean.ConnectionFactoryBean">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/zhou?useSSL=false"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

再次测试

@Test
public void t3() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
    Connection conn = (Connection) context.getBean("conn");
    System.out.println(conn);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

没有任何问题

com.mysql.jdbc.JDBC4Connection@13f604a

  
 
  • 1

就这样,轻松的解决了耦合问题,这就是Spring。

3.1.5、FactoryBean实现原理

  1. 通过配置文件获取 conn 信息,并通过 instanceof 判断是否是 FactoryBean 的实现类
  2. Spring 按照接口规定调用 getObject() —> Connection
  3. 返回 Connection

3.2、实例工厂

目的: 避免Spring框架的侵入,整合遗留系统

ConnectionFactory

package 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/zhou?useSSL=false", "root", "root");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

spring.xml

<bean id="connectionFactory" class="factorybean.ConnectionFactory"/>

<bean id="con" factory-bean="connectionFactory" factory-method="getConnection"/>

  
 
  • 1
  • 2
  • 3

test

@Test
public void t5() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
    Connection conn = (Connection) context.getBean("con");
    System.out.println(conn);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
com.mysql.jdbc.JDBC4Connection@fcf36f

  
 
  • 1

3.3、静态工厂

StaticConnectionFactory

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

spring.xml

<bean id="conn" class="factorybean.StaticConnectionFactory" factory-method="getConnection"/>

  
 
  • 1

test

@Test
public void t3() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
    Connection conn = (Connection) context.getBean("conn");
    System.out.println(conn);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
com.mysql.jdbc.JDBC4Connection@1aab8c6

  
 
  • 1

四、总结

在这里插入图片描述

五、写在最后

座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!

一起学习的可以私信博主或添加博主微信哦。

专栏:订阅专栏 ✅
关注:关注博主 🆙

文章来源: blog.csdn.net,作者:王子周棋洛,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/m0_53321320/article/details/125854266

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。