欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

06-Spring复杂对象的创建

程序员文章站 2022-05-29 14:46:32
...

上一篇:05-Spring反转控制IOC 与 依赖注入DI概念https://blog.csdn.net/fsjwin/article/details/109411172
什么是复杂对象?
不能通过new的方式创建出来的对象就是复杂对象。
下面试对简单对象和复杂对象的说明,这样的话对简单对象和复杂对象就有了具体的认识。这里非常重要。学习一定要有调性,有节奏,这样掌握起来就得心应手。
06-Spring复杂对象的创建
对于复杂对象的创建无法使用new的方式创建了。但是此路不通,别路通,下面介绍三种创建复杂对象的方式:

  • 1.FactoryBean
  • 2.实例工厂
  • 3.静态工厂

1.FactoryBean创建复杂对象

以创建Connection为例。

  1. 引入mysql的驱动
  <dependency>
     <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.48</version>
  </dependency>
  1. 创建MyConnectionFacoryBean实现FactoryBean接口
package base.comobjectcreate.factorybean;

import org.springframework.beans.factory.FactoryBean;

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

/**
 * @author yuhl
 * @Date 2020/11/1 9:50
 * @Classname MyFacoryBean
 * @Description FactoryBean创建复杂对象
 */
public class MyConnectionFacoryBean implements FactoryBean<Connection> {
    //创建对象
    @Override
    public Connection getObject() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("mysql://localhost:3306/yuhl", "root", "root");
        return connection;
    }

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

    /**
     *
     * @return
     * 是否是单利模式 true:单利模式
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

  1. 配置文件
    返回的就是Connection对象了。
<bean id="conn" class="base.comobjectcreate.factorybean.MyConnectionFacoryBean"/>
  1. 测试获得Connect对象
    @Test
    public void test11() {
        System.out.println("test9-------------------");
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Connection connection = (Connection) ctx.getBean("conn");
        Connection connection2 = (Connection) ctx.getBean("conn");
        System.out.println(connection);
        System.out.println(connection2);
    }
  1. 怎么获得MyConnectionFacoryBean对象?
    &conn的使用
/**
     * &conn 获取 MyConnectionFacoryBean对象
     */
    @Test
    public void test12() {
        System.out.println("test9-------------------");
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        MyConnectionFacoryBean connection = (MyConnectionFacoryBean) ctx.getBean("&conn");
        System.out.println(connection);

    }
  1. 对于Connection对象,没有应该都是不同的。所以不能使用单利模式
  /**
     *
     * @return
     * 是否是单利模式 true:单利模式
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
  1. MyConnectionFacoryBean类中的用户名和密码及连接怎么解耦
    此类对这三个有依赖,那么有依赖就可以注入,所以我们的思想是注入进去。
    MyConnectionFacoryBean.java 定义成员变量
package base.comobjectcreate.factorybean;

import org.springframework.beans.factory.FactoryBean;

import java.security.spec.PSSParameterSpec;
import java.sql.Connection;
import java.sql.DriverManager;

/**
 * @author yuhl
 * @Date 2020/11/1 9:50
 * @Classname MyFacoryBean
 * @Description FactoryBean创建复杂对象
 */
public class MyConnectionFacoryBean implements FactoryBean<Connection> {
    String driver;
    String url;
    String username;
    String password;

    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;
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    //创建对象
    @Override
    public Connection getObject() throws Exception {
        Class.forName(driver);
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }

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

    /**
     *
     * @return
     * 是否是单利模式 true:单利模式
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

配置文件修改:

 <bean id="conn" class="base.comobjectcreate.factorybean.MyConnectionFacoryBean">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/spring?useSSl=false"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

正常测试通过。

  1. jdbc:mysql://127.0.0.1:3306/spring?useSSl=false 为什么要加useSSl=false
    myslq高版本默认使用ssl加密,如果不主动关闭的话,日志会有警告,但是不影响使用。
    06-Spring复杂对象的创建
  2. 原理解析(简易版)
    当使用
MyConnectionFacoryBean connection = (MyConnectionFacoryBean) ctx.getBean("&conn");

创建对象的时候,spring层会调用object.instanceOf()方法,看当前对象是不是FacoryBean对象(实现类),如果是,则调用其getObject()方法返回返回值。
当然会校验isSinglton是否为true,返回单利或者非单利对象。

2.实例工厂创建复杂对象

FactoryBean有侵入。
整合遗留系统。

对于已经有的class文件,仅通过配置的方式创建conn对象。

  1. 已经拿到的class文件的源码,这个类很有可能就是个大框架中提供好的
package base.comobjectcreate.factorybean;

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

/**
 * @author yuhl
 * @Date 2020/11/1 10:59
 * @Classname ConnectionFactory
 * @Description 已经拥有的类
 */
public class ConnectionFactory {
    public Connection getConnection(){
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/spring", "root", "root");
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
        }
       return connection;
    }
}

  1. 配置文件
  <bean id="connectionFactory" class="base.comobjectcreate.factorybean.ConnectionFactory"/>
  <bean id="connection" factory-bean="connectionFactory" factory-method="getConnection"/>
  1. 测试
  /**
     * 实例工厂
     * 为什叫:实例工厂呢?因为需要先new ConnectionFactory(),获得工厂的实例,然后调用new ConnectionFactory().getConnection()方法,所以叫实例工厂
     */
    @Test
    public void test13() {
        System.out.println("test9-------------------");
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Connection connection = (Connection) ctx.getBean("connection");
        System.out.println(connection);

    }

为什叫:实例工厂呢?

  • 因为需要先new ConnectionFactory(),获得工厂的实例,然后调用new ConnectionFactory().getConnection()方法,所以叫实例工厂

3.静态工厂创建复杂对象

  1. 静态工厂和实例工厂唯一的区别就是getConnect()方法是静态的。随之配置有所不同
    StaticConnectionFactory.java
package base.comobjectcreate.factorybean;

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

/**
 * @author yuhl
 * @Date 2020/11/1 10:59
 * @Classname ConnectionFactory
 * @Description 静态工厂,静态方法
 */
public class StaticConnectionFactory {
    public static Connection getConnection(){
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/spring", "root", "root");
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
        }
       return connection;
    }
}

  1. 配置文件
<!--静态工厂-->
    <bean id="staticConnectionFactory" class="base.comobjectcreate.factorybean.StaticConnectionFactory" factory-method="getConnection"/>

  1. 测试
   /**
     * 静态工厂
     */
    @Test
    public void test14() {
        System.out.println("test9-------------------");
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        Connection connection = (Connection) ctx.getBean("staticConnectionFactory");
        System.out.println(connection);

    }

4.总结

06-Spring复杂对象的创建
对接第三方框架的时候,你没的选择,人家是什么你就使用什么样的方式去使用。
但是如果是新项目建议使用FactoryBean的方式。
下一篇:07-Spring对象的创建次数 singleton|prototype https://blog.csdn.net/fsjwin/article/details/109427054