一、什么是简单对象?

简单对象:指的是不能间接通过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也能对其进行整合