注解说明
When used as a type-level annotation in conjunction with {@link org.springframework.stereotype.Component @Component}, {@code @Scope} indicates the name of a scope to use for instances of the annotated type.
当和@Component一同使用,可以指定Bean的作用域。
@Scope默认作用域
单例(singleton)
针对一个BeanName,在spring容器中只存在一个Bean,不管怎么获取Bean都是得到相同的Bean。
多态(prototype)
针对一个BeanName,每次调用spring的getBean方法,会重新生成一个Bean。
request(Web专用)
针对一个BeanName,同一个请求生命周期内,多次调用spring的getBean方法得到的Bean是同一个;不同请求调用spring的getBean方法得到的Bean不一样。
session(Web专用)
针对一个BeanName,同一个session的所有请求,多次调用spring的getBean方法得到的Bean是同一个;不同session的请求调用spring的getBean方法得到的Bean不一样。
自定义
spring预留了实现自定义作用域的方式。
第一步,实现org.springframework.beans.factory.config.Scope接口生成自定义实现类,比如spring自带的SimpleThreadScope就是基于线程作用域的实现类,可以支持同一个线程,多次调用spring的getBean方法得到的Bean是同一个,不同线程调用spring的getBean方法得到的Bean不一样。
第二步,调用容器的beanFactory的registerScope方法注册自定义的作用域名称和实现之间的关系。比如,执行代码beanFactory.registerScope(“thread”, new SimpleThreadScope()),就完成了注册工作。之后,通过@Scope(value = “thread”)即可声明某个Bean使用thread级别的作用域。
属性说明
/**
* 同 scopeName
*/
@AliasFor("scopeName")
String value() default "";
/**
* 作用域的名称,通过名称寻找实现类
*/
@AliasFor("value")
String scopeName() default "";
/**
* 作用域的代理模式,
* 一个非单例的bean通过@Autowared自动注入到其他bean,
* 如果不设置这个属性,会导致其作用域退化为单例
* INTERFACES : 使用JDK动态代理
* TARGET_CLASS : 使用CGLIB动态代理
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
使用示例
正常使用
@Service
public class SingleService {
private ProtoService protoService;
public ProtoService getProtoService() {
return protoService;
}
@Autowired
public void setProtoService(ProtoService protoService) {
this.protoService = protoService;
}
}
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ProtoService {
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.scan("com.example.scope");
applicationContext.refresh();
System.out.println("通过自动注入获取:");
SingleService singleService = applicationContext.getBean(SingleService.class);
System.out.println(singleService.getProtoService());
System.out.println(singleService.getProtoService());
System.out.println("通过getBean方法获取:");
System.out.println(applicationContext.getBean(ProtoService.class));
System.out.println(applicationContext.getBean(ProtoService.class));
}
打印结果:
通过自动注入获取:
com.example.scope.ProtoService@25ce9dc4
com.example.scope.ProtoService@74ea2410
通过getBean方法获取:
com.example.scope.ProtoService@17f62e33
com.example.scope.ProtoService@76b1e9b8
如果不设置上述代码中的proxyMode = ScopedProxyMode.TARGET_CLASS
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ProtoService {
}
打印结果:
通过自动注入获取:
com.example.scope.ProtoService@6f46426d
com.example.scope.ProtoService@6f46426d
通过getBean方法获取:
com.example.scope.ProtoService@73700b80
com.example.scope.ProtoService@49c7b90e
从打印结果中可以看到,自动注入的是单例,多次访问得到的都是同一个Bean,但是不影响通过getBean方法访问得到不同的Bean
相关源码
ConfigurationClassBeanDefinitionReader
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
// Consider scoping
// 和@Bean一起使用的@Scope由此代码解析
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
// 如果存在@scope,将scope属性设置给beanDefinition
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// Replace the original bean definition with the target one, if necessary
// 如果proxyMode 不为空,则生成一个包含代理信息的BeanDefinition取代原来的BeanDefinition,用于@Autowired自动注入
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
......
}
AnnotationScopeMetadataResolver
/**
* 从beanDefinition里面解析scope元数据
* 和@Component一起使用的@Scope由此代码解析
*/
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
if (attributes != null) {
// 如果存在@scope,将scope属性设置给beanDefinition
metadata.setScopeName(attributes.getString("value"));
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}
AbstractBeanFactory
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
......
try {
......
// Create bean instance.
// 开始bean的创建工作
if (mbd.isSingleton()) {
// 单例将创建工作(createBean)封装在 ObjectFactory里,然后调用getSingleton方法
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 根据name和beanName获得合适的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// 如果这个是多态
Object prototypeInstance = null;
try {
// 调用bean创建前的相关工作
beforePrototypeCreation(beanName);
// 多态直接创建对象
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 调用bean创建后的相关工作
afterPrototypeCreation(beanName);
}
// 根据name和beanName获得合适的对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 除了单例和多态以外的自定义scope
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ′" + beanName + "'");
}
// 根据scopeName找到自定义作用域实现行为
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 将自定义的创建bean的行为封装在ObjectFactory里,然后调用Scope#get方法进行自定义创建行为
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
// 根据name和beanName获得合适的对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
......
return (T) bean;
}
本文暂时没有评论,来添加一个吧(●'◡'●)