spring学习记录(七)

时间:2022-12-11 08:56:20

Spring中对象分类

Spring是一个功能强大的容器,容器中存储的是一个一个的对象,容器中的对象分为:

  • 简单对象
  • 复杂对象

简单对象就是可以通过构造器直接new 出来的对象;
复杂对象是不可以直接通过构造器直接new出来的对象。
无论是简单对象,还是复杂对象,都是在Spring的配置文件中通过bean标签来定义。
简单对象:

<bean id="person" name="p1" class="com.huwc.bean.Person">
</bean>

复杂对象的定义有三种:

  1. 通过实现FactoryBean实现
  2. 通过实例工厂实现
  3. 通过静态工厂实现

我们主要看一下第一种:通过实现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>

上面的例子中,我们可以看到:

  1. 工厂bean需要实现Spring中的FactoryBean接口
  2. 实现接口中定义的getObject、isSingleton、getObjectType三个方法
  3. 在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);

结果:
spring学习记录(七)

  • 配置文件中为prototype,而接口方法中返回true:
    结果:
    spring学习记录(七)

以上,可以看出:

  • 当配置文件和isSingleton方法中都指定了创建模式,只要有一个地方为非单例,则无论另一边如何配置,则对象都会以非单例模式来进行创建。
  • 实际开发中,如果使用了FactoryBean接口来实现复杂对象,则最好不要在xml配置中设置prototype属性,否则将降低程序的可读性。