目录
一、Spring 工厂创建复杂对象
1、什么是复杂对象
2、 Spring 工厂创建复杂对象的 3 种方式
(1)FactoryBean 接口
开发步骤:
细节:
FactoryBean 的实现原理[简易版]
Factory Bean 总结
(2)实例工厂
(3)静态工厂
3、Spring 工厂创建对象的总结
二、控制 Spring 工厂创建对象的次数
1、如何控制简单对象的创建次数
2、如何控制复杂对象的创建次数
3、为什么要控制对象的创建次数
一、Spring 工厂创建复杂对象
1、什么是复杂对象
我们目前学习的都是创建的简单对象
简单对象,指的就是可以直接通过 new 构造方法来创建的对象
所以我们之前的 USerService ,Person,UserDAO 等都是简单对象
复杂对象,指的就是不能直接通过 new 构造方法创建的对象
我们之前在 JDBC 中接触过的 Connection 就是复杂对象
2、 Spring 工厂创建复杂对象的 3 种方式
(1)FactoryBean 接口
开发步骤:
1、实现 FactoryBean 接口
2、Spring 配置文件的配置
实现 FactoryBean 接口:
作为 FactoryBean 来讲,这个接口在我们创建复杂对象的时候,我们要自己定义一个类,比如:MyFactoryBean ,它要实现我们这个 FactoryBean 接口中所规定的方法
FactoryBean 中规定了三个方法来让我们实现:
1、getObject( ); 用于书写创建复杂对象的代码,并把复杂对象作为方法的返回值返回
2、getObjectType( ); 返回所创建复杂对象的 Class 对象
3、isSingleton( ); 如果这个复杂对象只创建一次就返回 true,如果后续调用过程当中每一次调用都需要创建一个新的复杂对象时,就返回 false
Spring 配置文件的配置
<bean id="connection" class="factorybean.ConnectionFactoryBean"/>
通过这个配置,一方面我们告诉了 Spring 我们创建了一个叫做 ConnectionFactoryBean 的类,另一方面,我们也希望通过 Spring 创建这个类的对象供我们后面进行使用
这里的配置虽然和我们之前简单对象的配置是一样的,但是含义却发生了变化
如果 Class 中指定的类型,是 FactoryBean 接口的实现类,那么通过 id 值获得的是这个类所创建的复杂对象
细节:
1、如果想获得 FactoryBean 类型的对象,可以使用 ctx.getBean("&connection"),获得的就是 ConnectionFactoryBean 对象
2、isSingleton 方法返回 true 只会创建一个复杂对象,返回 false 每一次都会创建新的对象
究竟是返回 true(能被共用) 还是 flase(不能被共用) 要根据对象的特点来决定
3、mysql 高版本在进行连接创建的时候,需要指定 SSL 证书,解决的方式:
url = "jdbc:mysql://localhost:3306/java?useSSL=false"
4、对于依赖注入的体会
把 ConnectionFactoryBean 中依赖的四个 String 信息进行了配置文件的注入
优点:解耦合
<bean id="connection" class="factorybean.ConnectionFactoryBean">
<property name="driverClassName" value="com.mysql.jdbc.mysql"></property>
<property name="url" value="jdbc:mysql://localhost:3306/java?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="paassword" value="123456"></property>
</bean>
FactoryBean 的实现原理[简易版]
我们来思考两个问题:
1、为什么 Spring 要规定 FactoryBean 接口让我们去实现,并且让我们把创建复杂对象的代码写在 getObject 方法中?
2、为什么通过 ctx.getBean("connection"); 获得的是复杂对象 Connection 而没有获得 ConnectionFactoryBean
其实这里蕴含着的最核心的原理就是我们之前学过的 接口回调
FactoryBean 本质上就是一个接口回调
第一步:根据 connection 获得 <bean 标签相关信息,然后通过 instanceof (FactortyBean) 来判断此时所创建的类是不是 FactortyBean 接口的实现,如果不是 FactortyBean 的实现,就是简单对象,直接 new 运算创建;如果是 FactortyBean 接口的实现,那么就要实现 FactortyBean 接口当中所规定的那三个方法
第二步:getObject 里写了复杂对象的创建代码
第三步:Spring 调用 getObject 的方法
为什么 Spring 要规定 FactoryBean 接口让我们去实现,并且让我们把创建复杂对象的代码写在 getObject 方法中?
1、提供一种更加灵活和可扩展的方式来创建 Bean,通过实现 FactoryBean 接口,我们可以在 getObject 方法中自定义创建对象的逻辑,而不受 Spring 默认的 Bean 创建规则的限制,这样一来,我们可以根据实际需求,自由地进行一些额外的操作,例如创建代理对象、动态生成实例等。
2、FactoryBean 接口还可以用于创建一些特殊类型的 Bean,例如代理对象、代理工厂等。通过在 getObjectType 方法中返回不同的类型,我们可以使用不同的实现类来创建不同的Bean 实例,从而实现更加灵活的 Bean 创建方式。
3、通过将复杂对象的创建代码放在 getObject 方法中,Spring 可以更好地管理 Bean 的生命周期和依赖关系。Spring 会在需要使用该 Bean 时,调用 FactoryBean 的 getObject 方法来获取实例化的对象,并且会对该对象进行依赖注入和生命周期管理,进一步增强了 Spring 框架的灵活性和可扩展性。
Factory Bean 总结
FactortyBean 是 Spring 当中用于创建复杂对象的一种方式,而且这种方式也是 Spring 原生提供的,后续我们学习 Spring 整合其它框架的时候,会大量应用到 FactortyBean
(2)实例工厂
应用实例工厂的主要原因:
1、避免 Spring 框架的侵入(使用 Spring 框架进行开发的时候,如果使用 FactortyBean ,必须要实现 Spring 所规定的 Factory 接口,这个时候,如果我们离开 Spring ,就意味着我们前面写的 FactortyBean 没有意义了)
2、整合遗留系统
我们要调用 getConnection 方法的时候,得去 new 一个 ConnectionFactory 对象,进而再去调用 getConnection 方法,所以我们把这样的 ConnectionFactory 叫做 实例工厂
public class ConnectionFactory {
public Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java?useSSL=false","root","123456");
return connection;
}
}
这个就类似于我们所说的遗留代码,此时我们只需要 Spring 去集成它就可以了
所以,作为我们所说的实例工厂,在它的开发过程当中,类和工厂我们都已经有用了,我们只需要去解决我们配置层面上的问题就行了
所以它的开发步骤中,我们主要看它的配置文件怎么处理:
<bean id="connectionFactory" class="factorybean.ConnectionFactory"></bean>、
<bean id="connection" factory-bean="connectionFactory" factory-method="getConnection“></bean>
(3)静态工厂
实例工厂创建连接对象的方法是实例方法,而静态工厂创建对象的方法是静态方法
public class StaticConnectionFactory {
public static Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java?useSSL=false");
return connection;
}
}
调用方法的时候,直接 StaticConnectionFactory.getConnection() 即可
静态工厂和实例工厂在配置文件上也有所区别:
<bean id="connection" class="factorybean.StaticConnectionFactory" factory-method="getConnection"></bean>
静态工厂由于不需要对象,直接通过方法就可以进行调用,所以直接写 factory-method 即可
3、Spring 工厂创建对象的总结
二、控制 Spring 工厂创建对象的次数
在前面学习复杂对象的时候,我们说可以实现 factoryBean 接口,而 factoryBean 接口里面有一个叫做 isSingleton 的方法,这个方法如果 返回 true 意味着只会创建一个复杂对象,如果返回 false 就会返回多个复杂对象
但是它仅仅解决的是复杂对象的创建问题,那么如果我们此时通过 Spring 工厂创建的是简单对象,该如何控制创建对象的次数呢?
1、如何控制简单对象的创建次数
<bean id="account" scope="singleton | prototype" class="scope.Account"></bean>
singleton : 只会创建一次简单对象
prototype : 每一次都会创建新的对象
如果不写 scope 属性,scope属性的默认值就是 singleton
2、如何控制复杂对象的创建次数
这个知识点前面以及提过了,这里就不再赘述了
FactoryBean{
isSingleton(){
return true 只会创建⼀次
return false 每⼀次都会创建新的
}
}
如果没有 isSingleton 方法,还是通过 scope 属性来进行对象创建次数的控制
3、为什么要控制对象的创建次数
有一些对象,是可以被大家共用的,能够被共用的对象,只创建一次就够了
但是有的对象不能被共用,就需要按照实际情况创建对象
所以只有把对象的创建次数进行管理起来之后,我们才能根据对象自身的特点来判断对象的创建次数
优点:节省不必要的内存浪费
什么样的对象可以被共用(只创建一次就行了)?
1. SqlSessionFactory
2. DAO
3. Service
什么样的对象每一次都要创建新的?
1. Connection
2. SqlSession | Session
3. Struts2 Action