专栏名称: Cocoa开发者社区
CocoaChina苹果开发中文社区官方微信,提供教程资源、app推广营销、招聘、外包及培训信息、各类沙龙交流活动以及更多开发者服务。
目录
相关文章推荐
51好读  ›  专栏  ›  Cocoa开发者社区

spring源码阅读3-1——bean的作用域

Cocoa开发者社区  · 公众号  · ios  · 2017-05-28 11:00

正文

java开发者都会在实体对象的属性中加上private关键字,而在业务类对外发放的方法中写上public关键字,这并不是习惯,而是开发者深谙其道,这就是java对象中filed的作用域。


举个例子,你家里的东西,都属于你家的,家门前的路是属于你和邻居们的,你爸爸的剃须刀是属于你爸爸的;这就是作用域,分清对象归属权限的作用。


而在spring容器所管理的组件,也是有作用域的。本章将会详细阐述bean的作用域,以及其和ApplicationContext、bean和beanFactory丝丝缕缕的联系。


俗话说,授之于鱼不如授之以渔,我们还是通过源码来学习,希望在这个过程大家都能够有所提升。


@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Scope {


/**

* Specifies the scope to use for the annotated component/bean.

* @see ConfigurableBeanFactory#SCOPE_SINGLETON

* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE

* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST

* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION

*/

String value() default ConfigurableBeanFactory.SCOPE_SINGLETON;


/**

* Specifies whether a component should be configured as a scoped proxy

* and if so, whether the proxy should be interface-based or subclass-based.

*

Defaults to {@link ScopedProxyMode#NO}, indicating that no scoped

* proxy should be created.

*

Analogous to {@code } support in Spring XML.

*/

ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;


}


在spring容器中,@Scope注解来声明实例的作用域,在源码中的注释中有这样一句话In this context, scope means the lifecycle of an instance。scope决定了实例的整个生命周期。


Scope注解的value值上方的注释告诉我们,当前有四个值:(高级版本更新了global session)

SCOPE_SINGLETON,SCOPE_PROTOTYPE,SCOPE_REQUEST,SCOPE_SESSION,下面分别来看看,这些作用域,有什么不同。

SCOPE_SINGLETON


从源码中可以看到,该作用域是spring默认的作用域。`singleton`想必大家都非常熟悉,没错,学习设计模式的时候第一个介绍的应该就是单例模式,也就是说,spring中的bean,默认情况下都是单例。复习下什么是单例:在应用中,有且只有一个实例。通过之前的bean管理的学习([《spring源码阅读2-2——bean的管理》](http://www.jianshu.com/p/3c225fc067a0)),我们知道容器中的单例都会被注册到spring容器中的缓存中,回顾下:

容器中的缓存对象


这回可以动态运行demo代码,证实下spring容器对于bean的管理。


//代码清单 1-1配置文件

com.nd.config.SpringConfig


@Configuration

@ComponentScan(basePackages = {"com.nd"})

public class SpringConfig {

}


//代码清单 1-2 main函数

com.nd.HelloApp


public class HelloApp {

public static void main(String[] args) {

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

HelloService helloService = context.getBean(HelloService.class);

System.out.println(helloService.sayHello());

}

}


//代码清单 1-3 bean

com.nd.HelloService


@Component

public class HelloService {

public String sayHello() {

return "Hello world!";

}

}


代码很简单,之前用的xml配置也被替换成注解配置了。


通过IDEA的debug功能,查看context的内容:


context下的beanFactory

singletonObjects与registeredSingletons


可以看到确实如之前所说,singletonObjects存放注册后的实例,而registeredSingletons存放的是注册实例的名称(类型是String)。而我们的组件helloService也在其中,这时候通过getBean方法就能够获取到该实例,运行程序,便可以看到我们最熟悉的Hello world!

SCOPE_PROTOTYPE


这个也很熟悉对吧,设计模式中有个原型模式。顾名思义,每一次获得的实例都是一个原型的拷贝(新的对象)。

我们看下这个给bean加上这个注解


@Component

@Scope(value = "prototype")

public class HelloService {

public String sayHello() {

return "Hello world!";

}

}


运行后再观察singletonObjects,已经没有注册该实例了。


只有14个注册的实例


但是程序运行结果依然是输出了最熟悉的Hello world!(具体如何实现日后会有机会展示的),这就是原型作用域的作用。

单例和原型的比较






请到「今天看啥」查看全文