3.1:Profile
随着软件运行环境的变化程序需要加载的bean是不同的。例如开发环境使用的数据库和运行环境使用的数据库是不同的。Spring提供了profile,可以决定哪一种bean需要被使用。使用时只需要将不同的Bean指定不同的Profile,然后将需要的Profile激活即可。在Spring4.0中对@profile进行了重构,使其基于了@Conditional
使用java配置声明Profile
//开发时使用的Profile
@configuration
@Profile("dev") //这个配置类中的所有bean都属于名为dev的Profile(Spring3.1有的)。
java配置类{}
//测试时使用的Profile
@configuration
@Profile("qc")
java配置类{}
@Configuration
java配置类{
@Profile("dev") //指定当前的Bean属于devProfile(Spring3.2有的)
@Bean
Bean配置方法{}
@Profile("qc")
@Bean
Bean配置方法{}
}
使用xml配置声明Profile
<beans xmlns="http://...."
profile = "dev"> //这个<beans>中包含的所有bean都属于devProfile
<bean>....</bean>
</beans>
//使用嵌套<beans>的方法实现单独为bean配置
<beans xmlns="http://...."> //这个<beans>中包含的所有bean都属于devProfile
<beans profile="dev">
<bean>...</bean>
</beans>
<beans profile="qc">
<bean>...</bean>
</beans>
</beans>
激活profile:
激活profile需要配置的两个属性是:spring.profiles.active 和 spring.profiles.default。
配置了active的profile为激活的,没有配置active是default生效,都没有配置都不生效。
配置位置有很多(查资料)
3.2:条件化Bean
如果有一个Bean需要在另外一个特定的Bean声明后才创建。在Spring4.0提供了 @Conditional。它可以用在@Bean配置方法上,只有指定的条件成立时才会创建这个bean,否则忽略。
例如:判断条件是环境变量中有“JAVA_HOME”。
@Configuration
java配置类{
@Bean
@Conditional(javaHomeExistsCondition.class) //配置比较类,这个类只需要实现Condition接口的matches方法即可。
javaBean配置方法(){...}
}
public class javaHomeExistsCondition implements Condition{ //Condition接口中的matches方法返回Boolean值决定是否验证通过,matches的两个参数很有用
public boolean matches(ConditionContext context , AnnotatedTypeMetadata metadata){
Environment emv = context.getEnvironment();
return env.containsProperty("JAVA_HOME");
}
}
上面的matches方法非常简单,但是功能却非常强大。
借助ConditionContext接口可以实现:
getRegistry() 返回BeanDefinitionRegistry检查bean定义。
getBeanFactory() 返回ConfigurableListableListableBeanFactory检查bean是否存在,探测bean的属性
getEnvironment() 返回Environment检查环境变量
getResourceLoader() 返回ResourceLoader读取并探测加载的资源
getClassLoader() 返回ClassLoader检查类是否存在
借助AnnotatedTypeMetadata接口可以检查带有@Bean注解的方法上还有什么其他注解
3.3:处理自动转配的歧义性
如果使用组件扫描自动装配Bean的话,Spring会寻找符合条件的Bean作为依赖注入,是当有多个Bean同时符合条件时,Spring不知道使用哪个Bean好。抛出异常:NoUniqueBeanDefinitionException。
解决这个问题可以通过:1、标识首选的Bean 2、限定自动装配的Bean (使用方法查资料)
3.4:Bean的作用域
Spring应用上下文中的bean默认都是单例的,但是单例的bean是非常理想的,有时候使用的bean时易变得,会保持某一状态的。Spring还为Bean指定了别的作用域
单例(Singleton) 在整个应用中只创建一个bean的实例。
原型(Prototype) 每次注入或者在上下文中获取的时候都创建一个新的。
会话(Session) Web应用中为每一个会话创建一个Bean实例
请求(Request) Web应用中为每一个请求创建一个Bean实例
配置bean的作用域
使用组件扫描发现bean
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class xxx{...}
在java配置中将bean
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public 类型 方法名(){...}
使用xml配置bean
<bean id = "xxx" class = "xxx.yyy" scope = "prototype"> </bean>
使用会话和请求作用域
将Bean声明为会话和请求作用域时有个问题:如果某些单例的bean依赖了这些bean,单例的bean创建的时候会话bean还不存在。Spring在这个问题上使用代理模式解决。
因此声明会话或者请求作用域时需要加一个参数:
@Scope(WebApplicationContext.SCOPE_SESSION , proxyMode = ScopedProxyMode.INTERFACES)
使用方法???????????????????????
3.5:运行时注入值
有时候我们需要注入一个字面值,但是这个字面值目前是不确定的或者以后可能会改变,那么我们就需要在运行时才将这个值注入。Spring中解决方案有:1、使用属性占位符 2、使用Spring表达式语言(SpEl)
注入外部值最简单的方法是声明属性源然后使用Environment来检索属性。
@Configuration
@PropertySource("classpath:/com/xxx/yyy/app.properties") //指定参数源
public class 类名(){
@Autowired
Environment env; //Environment中重载的getProperty方法可以获取参数、获取参数并设置默认值、获取参数并解析为类。
@Bean
public 类型 方法名(){
String aaa = env.getProperty("aaa"); //检索属性
}
}
app.properties文件内容
aaa = 需要的实际参数
解析属性占位符
Spring支持将属性定义到外部,并使用占位符将其插入到Spring bean中。在Spring装配中使用${}包装属性名称
xml中:
<bean id = "" class = "">
<property name="" value = ${xxx.yyy}>
</bean>
具体使用方法(查资料)???????????????????
使用SpEL表达式将外部值引入(查资料)??????????????????