一、bean的作用域
默认情况下,Spring应用上下文中所有bean都是以单例(singleton)的形式创建的。
Spring定义的多种作用域,可以基于这些作用域创建bean,包括:
1、单例(singleton):整个应用中,只创建bean的一个实例。
2、原型(prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
3、会话(session):在web应用中,为每个会话创建一个bean实例。
4、请求(request):web应用中,为每个请求创建一个bean实例。
想要改变bean的作用域,可以通过@Scope注解,它可以与@Component(注解扫描)或@Bean(JavaConfig)一起使用。
- 单例和原型在注解扫描中的使用:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TestScope {
}
- 单例和原型在JavaConfig中的使用:
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public TestScope testScope(){
return new TestScope();
}
其中ConfigurableBeanFactory的常量有两个:也可以直接填写字符串(不推荐,难免有手抖的时候,哈哈)
- 单例和原型在XML中的使用:
<bean id="testScope" class="com.caofanqi.bean.TestScope" scope="prototype" />
- 会话和请求
@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.INTERFACES) //会话作用域,接口代理模式
@Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode = ScopedProxyMode.TARGET_CLASS) //会话作用域,CGLib代理模式
@Scope(value = WebApplicationContext.SCOPE_REQUEST,proxyMode = ScopedProxyMode.INTERFACES) //请求作用域,接口代理模式
@Scope(value = WebApplicationContext.SCOPE_REQUEST,proxyMode = ScopedProxyMode.TARGET_CLASS) //请求作用域,CGLib代理模式
将value的值设置为SCOPE_SESSION,Spring会为Web应用的每个会话创建一个实例。这会创建多个实例,但是对于给定的会话只会创建一个实例,在当前会话,bean相当于单例的。
ScopedProxyMode解决了将会话作用域的bean 注入到单例中遇到的问题,Spring在装载单例bean的时候,不会真正的注入会话模式的bean,而是出入一个会话作用域的代理bean,真正调用会话作用域的方法时,代理会进行解析,并将调用委托给真正的会话作用域bean。会话作用域的bean是接口的话,可以使用INTERFACES,如果是一个类的话需要使用TARGET_CLASS。
请求作用域类似会话作用域。
在XML中,要使用Spring aop名称空间的一个新元素:
默认情况下,它会使用CGLib创建目标类的代理。我们可以将proxy-target-class属性设置为false,要求它进行基于接口的代理:
<bean id="testScope" class="com.caofanqi.bean.TestScope" scope="session">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
二、运行时注入
Spring提供了两种在运行时求值的方式:属性占位符、Spring表达式语言(SpEL)
1、注入外部的值:声明属性源,通过Spring的Environment来检索属性
① 创建properties属性文件,如下:
title=zhangsan
price=23
②创建JavaConfig配置
@Configuration
@PropertySource("classpath:app.properties") //属性文件位置
public class UserConfig {
@Autowired
private Environment environment;
@Bean
public User user(){
//getProperty获得属性值
return new User(environment.getProperty("title"),environment.getProperty("price",Double.class));
}
}
2、Environment的API
获取属性的getProperty有四个重载的方法
String getProperty(String key); //可能得到null
String getProperty(String key, String defaultValue); //当属性不存在时,可以取默认值
<T> T getProperty(String key, Class<T> targetType); //根据类型获取
<T> T getProperty(String key, Class<T> targetType, T defaultValue); //根据类型获取,取不到取默认值
希望属性必须要定义:如果,key没有定义,竟会抛出异常
String getRequiredProperty(String key) throws IllegalStateException;
检查某个属性是否存在
boolean containsProperty(String key);
3、解析属性占位符:占位符的形式是 “${key} ”
在XML中可以直接使用${key} 获取值,如:
<context:property-placeholder location="app.properties"/>
<bean id="user" class="com.com.caofanqi.User">
<constructor-arg value="${title}" />
<constructor-arg value="${price}" />
</bean>
如果使用注解扫描初始化,我们使用@Value注解,它的使用方式和@Autowired相似。
public User( @Value("${title}")String title, @Value("${price}")Double price) {
this.title = title;
this.price = price;
}
4、SpEl,我用的不多
标签:String,作用域,Spring,会话,bean,key From: https://blog.51cto.com/caofanqi/5754593