共计 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 也能对其进行整合