关于spring:五Spring创建复杂对象和创建对象的次数

6次阅读

共计 4132 个字符,预计需要花费 11 分钟才能阅读完成。

一、什么是简单对象?

简单对象:指的是不能间接通过 new 构造方法创立的对象,那么反过来 简略对象 就是
能够间接通过 new 构造方法创建对象
那么这类简单对象有哪些呢?有比方咱们比拟相熟的 Mybatis 中的 SqlSessionFactory
和 Connection 对象
简略对象的创立比拟好了解,Spring 也应该容易做到,那么简单对象呢?如果简单对象 Spring
也能做到,那么 Spring 可就牛逼了


二、Spring 工厂创立简单对象的三种形式
2.1 实现 FactoryBean 接口

当咱们实现了 FactoryBean<T> 接口,那么咱们就必须重写其三种办法,上面为其对应的三种
办法
1.public Object getObject()
该办法用于书写创立简单对象的代码 并 把简单对象作为办法的返回值 返回
* 如果申明了 T 的类型,那么就会间接返回对应类型的对象
你晓得为什么咱们须要重写这个办法吗?这是因为每个简单对象创立的代码未必一样,所以
须要咱们本人去重写来创立
2.public Class getObjectType()
该办法用于返回简单对象的 Class 对象
3.public boolean isSingleton()
 返回 true   示意 该对象只需创立一次
返回 false  示意 每次调用都须要创立一个新的简单对象


2.2 以创立 Connection 对象为例,上面展现其实现步骤

第一步:引入 mysql 相干依赖
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.48</version>
</dependency>
第二步:新建一个类实现 FactoryBean<Connection> 接口,并重写其三个办法
public class ConnectionBeanFactory implements FactoryBean<Connection> {
    @Override
    public Connection getObject() throws Exception {Class.forName("com.mysql.jdbc.Driver");
        // 留神: 如果是 mysql8.0 以上的,那么还须要在连贯 url 处增加上对应的时区参数
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "admin");
        return conn;
    }

    @Override
    public Class<?> getObjectType() {return Connection.class;}

    @Override
    public boolean isSingleton() {return false;}
}
第三步: 配置 Spring 的配置文件
<!-- 通过实现 FactoryBean 接口创立简单对象 -->
<bean id="conn" class="cn.paul.spring.demo.hellospring.beanFactory.ConnectionBeanFactory"/>
留神: 如果 Class 中指定的类型 是 FactoryBean 的实现类,那么通过 id 值获取到的是
调用 ConnectionBeanFactory 办法中重写的 getObject()办法所创立的对象

问题: 如果我就是想创立这个 ConnectionBeanFactory 的对象,该如何创立呢?
答案: 咱们只须要在代码层面加上 ”&” 即可,示例如下

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
ConnectionBeanFactory conn = (ConnectionBeanFactory) ctx.getBean("&conn");
System.out.println("conn =" + conn);

2.3 对于 isSingleton()办法,如果返回 true,则只会创立一个对象,即咱们所谓的单例,如果为 false,则每次调用 getBean()办法都会创立一个对象,为多例;
依据这个特点,决定是返回 true(SqlSessionFactory)还是 false(Connection)

为什么 Connection 对象是单例的?这是因为每获取一次 Connection 对象,那么就相当于
开启了一个事务,显然让这个对象共享,无异导致事务提交的凌乱,齐全打乱了事务的隔离个性

2.4 如果波及到 mysql 高版本的连贯创立时,须要指定不应用 SSL 证书来解决 warn 问题,配置如下

url="jdbc:mysql://localhost:3306/suns?userSSL=false"

备注:如果波及到 8.x 版本的 mysql,还要设置对应的时区,该配置可自行百度

2.5 四因素的代码优化
看到下面在代码层面将四因素都写死在代码下面了,这其实也是一种耦合的状况,所以咱们能够应用 Spring 配置文件对其进行 属性注入,改写如下
2.5.1 代码层面定义定义对应的成员变量,并且提供相应的 setter 和 getter 办法

public class ConnectionBeanFactory implements FactoryBean<Connection> {
    // 定义对应的四因素
    private String driverClassName;
    private String url;
    private String username;
    private String password;

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

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

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

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

    public String getDriverClassName() {return driverClassName;}

    public String getUrl() {return url;}

    public String getUsername() {return username;}

    public String getPassword() {return password;}

    @Override
    public Connection getObject() throws Exception {Class.forName(driverClassName);
        // 留神: 如果是 mysql8.0 以上的,那么还须要在连贯 url 处增加上对应的时区参数
        Connection conn = DriverManager.getConnection(url, username, password);
        System.out.println("Creating Connection Bean.......");
        return conn;
    }

    @Override
    public Class<?> getObjectType() {return Connection.class;}

    @Override
    public boolean isSingleton() {return true;}
}

2.5.2 在 Spring 的配置文件中实现属性注入

<bean id="conn" class="cn.paul.spring.demo.hellospring.beanFactory.ConnectionBeanFactory">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test?userSSL=false"/>
    <property name="username" value="root"/>
    <property name="password" value="admin"/>
</bean>

2.5.3 依赖注入的领会(DI)

通过下面的配置,将 Spring 的属性注入的精华利用得非常透彻,其益处在于很好地解耦合
如果哪天我感觉配置的信息不适宜我用,那么我就就能够间接批改配置文件以达到成果

三、FactoryBean 的实现原理 (简易版)
在 java 编程体系中,许多开源框架都应用到了反射和接口回调, 故江湖称: 接口加反射,什么都能做。
须要思考上面的问题

1> 为什么 Spring 规定 FactoryBean 接口 实现 并且通过 getObject()办法能力获取对应的简单对象?
2> 为什么 ctx.getBean("conn")取得的是简单对象 Connection 而不是其自身 ConnectionFactoryBean?

Spring 外部运行流程

1> 通过 ctx.getBean("conn")获取 ConnectionFactoryBean 对象,而后通过 instanceOf()
判断出其是否是 FactoryBean 接口的实现类
2> 如果是 FactoryBean 接口的实现类的话,Spring 依照规定,调用其重写的 getObject()办法
来创立 Connection 对象
3> 最终将 Connection 对象返回

四、FactoryBean 总结

Spring 中用于创立简单对象的一种形式,也是 Spring 原生提供的,是其整合其余框架中
会大量应用 FactoryBean

五、实例工厂
5.1 为什么须要实例工厂?

1> 在没有 Spring 的根底上(即没有了 FactoryBean 接口), 咱们须要一个工厂来生成简单对象,如果哪天咱们不必 Spring 了,也能有这个工厂来生产对象
2> 属于遗留的工厂类,Spring 也能对其进行整合
正文完
 0