Spring中对象分类
Spring是一个功能强大的容器,容器中存储的是一个一个的对象,容器中的对象分为:
- 简单对象
- 复杂对象
简单对象就是可以通过构造器直接new 出来的对象;
复杂对象是不可以直接通过构造器直接new出来的对象。
无论是简单对象,还是复杂对象,都是在Spring的配置文件中通过bean标签来定义。
简单对象:
<bean id="person" name="p1" class="com.huwc.bean.Person">
</bean>
复杂对象的定义有三种:
- 通过实现FactoryBean实现
- 通过实例工厂实现
- 通过静态工厂实现
我们主要看一下第一种:通过实现FactoryBean来创建复杂对象
@Data
public class ConnectionFactoryBean implements FactoryBean<Connection> {
private String driverClass;
private String url;
private String username;
private String password;
@Override
public Connection getObject() throws Exception {
System.out.println("ConnectionFactoryBean.getObject");
Class.forName(driverClass);
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return false ;
}
}
xml中的定义:
<bean id="conn" class="com.huwc.factorybean.ConnectionFactoryBean" scope="prototype">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///test?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
</bean>
上面的例子中,我们可以看到:
- 工厂bean需要实现Spring中的FactoryBean接口
- 实现接口中定义的getObject、isSingleton、getObjectType三个方法
- 在spring的配置文件中进行配置
学习中,对复杂对象的创建模式,即:是单例模式,还是非单例模式产生了兴趣:实现了FactoryBean借口的工厂类中,isSingleton方法返回的true或者false,理论上决定了对象在Spring中是以单例创建(返回true时为单例,false为非单例),还是非单例创建;另外,在Spring配置文件中定义对象的时候,有一个属性 scope 也能决定对象是单例还是非单例的(不声明或者声明为singleton为单例,声明为prototype为非单例)。那么,如果这两个地方的声明不同,那么会产生什么情况?我们动手来看一下:
- 配置文件中为singleton,isSingleton方法返回false
<bean id="conn" class="com.huwc.factorybean.ConnectionFactoryBean" scope="singleton">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///test?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
</bean>
public boolean isSingleton() {
return false ;
}
测试程序:
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Connection conn1 = (Connection) ctx.getBean("conn");
Connection conn2 = (Connection) ctx.getBean("conn");
System.out.println("conn1 = " + conn1);
System.out.println("conn2 = " + conn2);
结果:
- 配置文件中为prototype,而接口方法中返回true:
结果:
以上,可以看出:
- 当配置文件和isSingleton方法中都指定了创建模式,只要有一个地方为非单例,则无论另一边如何配置,则对象都会以非单例模式来进行创建。
- 实际开发中,如果使用了FactoryBean接口来实现复杂对象,则最好不要在xml配置中设置prototype属性,否则将降低程序的可读性。