一、什么是简单对象?
简单对象:指的是不能间接通过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也能对其进行整合
发表回复