Spring中singleton和prototype的区别?

下面是@Configuration里的一个例子

@Configuration
public class AppConfig {
    @Bean//默认方法名为BeanID
    public UserDAO userDAO() {
        return new UserDAOImpl();
    }

    @Bean("userService")
//    @Scope("singleton") //默认情况下,scope="singleton"--表示单利
    @Scope("prototype") //多例模式
    public UserService initService() {
        UserService userService = new UserServiceImpl();
        userService.setUserDAO(userDAO());
        return userService;
    }
}


这个配置就等同于之前在xml里的配置
<!--    <context:component-scan base-package="top.xiongmingcai.spring"/>-->
<bean class="top.xiongmingcai.spring.injection.dao.UserDAOImpl" id="userDAO"/>

<bean class="top.xiongmingcai.spring.injection.service.UserServiceImpl" id="singleton" scope="prototype">
    <property name="userDAO" ref="userDAO"/>
</bean>

@Scope("Singleton") 或者 @Scope,因为默认情况下就是 单例的;

区别

public class InjectionApplication {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:injection.xml");
        //UserService userService = (UserService) ctx.getBean("userService");
        //UserService userService2 = (UserService) ctx.getBean("userService");

       // System.out.println(userService ==  userService2);
    }
}

单例模式多例模式区别

如图所示:单例模式在IOC初始化时就会实例化对象、prototype则在
访问 ctx.getBean("userService") 创建对象

总结:

  1. singleton 只有一个实例,也即是单例模式。
  2. prototype 访问一次创建一个实例,相当于new。

应用场合:

  • 1.需要回收重要资源(数据库连接等)的事宜配置为singleton,如果配置为prototype需要应用确保资源正常回收。
  • 2.有状态的Bean配置成singleton会引发未知问题,可以考虑配置为prototype。

扩展

在Spring2.0中除了以前的Singleton和Prototype外又加入了三个新的web作用域,分别为 request、session和 global session。

  1. request,如果在同一个“request”请求内,对象是同一个,不同的请求,IOC容器会创建不同的对象
  2. session,同一个session内部,多次调用getBean()获取的是同一个对象,不同的session IOC会创建不同的对象

lazy-init -->表示延迟初始化(懒加载)

@Lazy
@Bean("userService")
//    @Scope("singleton") //默认情况下,scope="singleton"--表示单利
//    @Scope("prototype") //多例模式
public UserService initService() {
    UserServiceImpl userService = new UserServiceImpl();
    userService.setUserDAO(userDAO());
    return userService;
}

lazy-init 会把对象实例化的过程,放在getBean()方法执行时。

1,设置为“true”--表示只有用到这个javaBean时,才会实例化。

注意:当scope属性为“prototype”多例模式时,lazy-init就会失效

azy-init 有自己的使用场景,因为其作用是,对象在第一次getBean()是被创建,所以可以起到减小服务器压力的作用。

(比如:当前有上千个类,但并不是所有的类都是目前需要的,有些是作为备用选项使用的。此时我们就可以使用lazy-init 来减轻服务器和内存的压力,有利于系统的快速启动)