读书笔记-spring高级装配bean
来源:互联网 发布:宏业计价软件视频教程 编辑:程序博客网 时间:2024/06/03 09:26
1.profile
spring会等到运行时根据环境决定需要创建哪个bean,所以一个war包可以适用于所有环境,不需要进行重新构建。
1.1配置profile
用@Profile注解指定某个bean属于哪个profile。
@Configuration@Profile("dev")public class DevConfig{ @Bean public DataSource dataSource() { return new ... }}
@Profile用在类级别上,表明类里面的bean只有dev profile激活时才会创建。
@Profile也可用在方法上。
XML配置如下:
<beans profile="dev"> <bean id="devBean"/></beans><beans profile="prod" <bean id="prodBean"/></beans>
1.2激活profile
2个相关属性:spring.profiles.active/spring.profiles.default
有多种方式设置这2个属性:
- 作为DispatcherServlet的初始化参数;
- 作为Web应用的上下文参数;
- 作为JNDI条目;
- 作为环境变量;
- 作为JVM的系统属性;
- 在集成测试类上,使用@ActiveProfiles注解设置;
例如在web.xml中设置默认profile:
<!--为上下文设置默认profile--><context-param> <param-name>spring.profiles.default></param-name> <param-value>dev</param-value></context-param><!--为servlet设置默认profile--><init-param> <param-name>spring.profiles.default></param-name> <param-value>dev</param-value></init-parm>
使用profile进行测试
spring提供了@ActiveProfiles,指定运行测试时要激活哪个profile。
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath*:httpclient-context.xml"})@ActiveProfiles("dev")public class CommandTest {
2 条件化的bean
当希望在某些特定条件下才创建bean,如某个bean只有在另外某个特定bean声明之后才创建,或者某个特定环境变量设置之后才会创建某个bean。
可以使用spring的@Conditional 注解。
@Bean @Conditional(ExistsCondition.class) public SgtPeppers sgtPeppers(){ return new SgtPeppers(); }
设置给@Conditional的类可以是实现了Condition接口的类型:
public class ExistsCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { Environment env = conditionContext.getEnvironment(); return env.containsProperty("propertyName");//检查propertyName属性 }}
ConditionContext是一个接口:
public interface ConditionContext { BeanDefinitionRegistry getRegistry();//可以检查bean定义 ConfigurableListableBeanFactory getBeanFactory();//用于检查bean是否存在 Environment getEnvironment();//检查环境变量是否存在以及值是什么 ResourceLoader getResourceLoader();//读取并探查ResourceLoader加载的资源 ClassLoader getClassLoader();//用于加载并检查类是否存在}
AnnotatedTypeMetadata也是接口,能够让我们检查带有@Bean注解的方法上还有其他注解:
public interface AnnotatedTypeMetadata { boolean isAnnotated(String var1);//用于判断带有@Bean注解的方法是否还有其他特定注解 Map<String, Object> getAnnotationAttributes(String var1); Map<String, Object> getAnnotationAttributes(String var1, boolean var2); MultiValueMap<String, Object> getAllAnnotationAttributes(String var1); MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);}
3处理自动装配的歧义性
如果某个bean要装配时,有多个实现,会造成冲突:
@Autowired public void setCompact(CompactDisc compact) { this.cd = compact; }public interface CompactDisc { void play();}@Componentpublic class CompactImpl1 implements CompactDisc {@Componentpublic class CompactImpl2 implements CompactDisc {
解决办法有:
3.1 设置首选的bean
@Component@Primarypublic class CompactImpl1 implements CompactDisc {
3.2限定自动装配的bean
@Qualifier注解
@Autowired @Qualifier("compactImpl1") public void setCompact(CompactDisc compact) { this.cd = compact; }
@Component注解声明的CompactImpl1类会创建为id为compactImpl1的bean(首字母小写),
@Qualifier(“compactImpl1”)指向组件扫描是创建的bean,即compactImpl1。
也可以为bean直接设置自己的限定符
@Component //或者是@Bean@Qualifier("impl1")public class CompactImpl1 implements CompactDisc {
自定义注解
当不想用@Qualifier或者出现@Qualifier定义重复时,可以自定义注解:
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Qualifierpublic @interface Impl1 {}
这样,只需要添加@impl1注解
@Component //@Bean@Impl1public class CompactImpl1 implements CompactDisc {
在注入时,也只需要添加@Impl1注解:
@Autowired @Impl1 public void setCompact(CompactDisc compact) { this.cd = compact; }
为了创建自定义的限定符注解,可以创建一个新的注解并添加上@Qualifier注解,这种技术可以用到很多的spring注解中。
4 bean的作用域
spring有多种作用域,用@Scope注解,默认单例:
单例(Singleton):整个应用中只有1个实例;
原型(Prototype):每次注入或者spring应用上下文获取时创建1个;
会话(Session):web应用中每个会话创建1个;如购物车;
请求(Request):web应用中每个请求创建1个;
@Component@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)//使用@Scope("prototype")也可以,但SCOPE_PROTOTYPE常量更加安全不易出错public class CompactImpl1
XML配置:
<bean class="chapter2.CompactImpl1" scope="prototype"/>
4.1 会话和请求作用域
会话作用域如下:
@Component @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.INTERFACES) public Shopping shop(){}
proxyMode的作用如下:
例如想把Shopping注入到单例Service的bean中,
@Componentpublic class Service { Shopping shopping; @Autowired public void setShopping(Shopping shopping){ this.shopping = shopping; }}
因为Service是单例bean,spring上下文加载时就会创建,但此时Shopping是会话作用域的,还不存在,知道某个用户进入系统时才会创建,而且系统里会有多个Shopping实例,spring应该是service的bean处理购物车功能时,使用的Shopping实例刚好是当前会话的bean。
所以spring会注入一个Shopping bean的代理,如下图,代理会暴露与Shopping bean相同的方法,当service真正调用Shopping方法时,代理会对其进行懒解析,将调用委托给会话作用域内真正的Shopping bean。
proxyMode = ScopedProxyMode.INTERFACES 表明创建的代理是基于接口的代理,代理要实现Shopping接口,Shopping需要是一个接口;
如果Shopping是一个具体类,此时,只能使用CGLib生成基于类的代理,此时proxyMode要设置成 ScopedProxyMode.TARGET_CLASS
请求作用域也是同样道理。
4.2 XML中声明作用域代理
<bean class="chapter2.Shopping" scope="session"><aop:scoped-proxy/></bean>
功能和@Scope注解的proxyMode属性功能相同,会告诉spring为bean创建一个作用域代理,默认使用CGLib创建目标类的代理,设置后会生成基于接口的代理。
5 运行时值注入
spring提供的两种运行时求值方式:
- 属性占位符
- spring表达式语言(SpEL)
5.1 注入外部的值
注入外部值:使用@PropertySource注解和Environment。
@Configuration@PropertySource("classpath:app.properties")public class CDplayerConfig { @Autowired Environment env; @Bean public CompactDisc disc() { return new SgtPeppers(env.getProperty("title")); }}
app.properties属性文件会加载到Environment中。
spring的Environment
getProperty()有四种重载方法:
第四种可以指定返回值类型和默认值,如下:
int result = env.getProperty("db.connection", Integer.class, 10);
将属性解析为类:
如果文件中没有定义该属性,得到的值是null。
env.getRequiredProperty()可以要求属性必须定义,否则抛出IllegalStateException异常。
解析属性占位符
spring配置中使用${….}
如果用组件扫描和自动装配创建和初始化bean时,没有指定占位符的配置文件和类了,此时可以使用@Value注解
@Bean public CompactDisc disc(@Value("${title}") String title) { this.title = title; }
5.2
- 读书笔记-spring高级装配bean
- Spring Bean 高级装配
- Spring入门之Bean高级装配
- Spring高级装配--条件化的bean
- Spring实战读书笔记 第二章 装配Bean
- Spring学习笔记(六) --- 装配Bean之高级装配
- Spring实战-读书笔记(章节三)-高级装配
- Spring学习笔记-C3-Spring装配Bean高级篇
- Spring装配Bean——高级装配之与环境相关的bean
- 一点一滴学习Spring(三)之bean高级装配
- Spring实战笔记——Bean的高级装配
- 《Spring In Action》 读书笔记(1) -- bean装配
- 《Spring In Action》 读书笔记(2) -- bean装配
- Spring Bean装配-自动装配
- spring 基本Bean装配
- Spring Bean 初级装配
- Spring中装配bean
- Spring bean装配
- 做互联网电视,要拼背景吗?
- 大牌对决 小米5 /魅族PRO 6 /iPhone 6s Plus拍照对比
- 奥巴马体验的那款VR纸盒是什么来头?
- Nginx搭建静态文件服务器
- SDNU OJ 1182 奖学金
- 读书笔记-spring高级装配bean
- 如何写一个RPC框架(二):利用Bean容器和动态代理简化客户端代码
- LCA模板
- 100+米/秒的赛车也能拍?快无边界vivo Xplay5抓拍F1方程式
- 1.17亿!腾讯守护者计划协助贵州公安破获全国最大金额电信诈骗
- 比起电影,VR新闻更有看头
- 腾讯互联网+创业大赛启动 亿万资源奖励双创新星
- FreeLine 踩坑记录
- 暴风年报解读:暴风说站在“黄金十年”的起跑线上,但首先要先“空心化”这一关