Spring之高级装配(二)
上一节提到Spring之装配bean(一),我们已经了解到了装配的基础知识,这部分是更为高级的bean装配技术。
高级装配内容:
- spring profile
- 有条件的bean
- 处理自动装配的歧义性
- bean的作用域
1.spring profile
应用程序从一个环境迁移到另一个环境。开发阶段,某些环境相关做法可能并不适合迁移到生产环境中,甚至几遍迁移过去也无法正常工作,所以在不同的环境中使用的bean可能不同。下面以datasource为例:
在Java配置类中配置(“dev”和“prod”生产环境):
@Configuration
public class DataSourceConfig{@Bean(destroyMethod="shutdown")@Profile("dev")public DataSource dataSource(){return new EmbeddedDatabaseBuilder().addScript("classpath:schema.sqsl").addScript("classpath:test-data.sql").build();}@Bean@Profile("prod")public DataSource dataSource(){JndiObjectFactoryBean jndi=new JndiObjectFactoryBean();jndi.setJndiName("jdbc/myDS");jndi.setResourceRef(true);jndi.setProxyInterface(javax.sql.DataSource.class);return (DataSource) jndi.getObject();}
}
在xml中配置:
<beans xmlns="......."><beans profile="dev"><jdbc:embedded-database id="dataSource"><jdbc:script location="classpath:schema.sql" /><jdbc:script location="classpath:test-data.sql" /></jdbc:embedded-database></beans><beans profile="qa"><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destory-method="close"p:url="jdbc:h2:tcp://dbserver/~/test".......p:maxActive="30"/></beans>
</beans>
激活(使用)哪一个profile:
<!--为应用山下文设置默认的profile-->
<context-param><param-name>spring.profiles.default</param-name><param-name>dev</param-name>
</context-param>
<!--为Servlet设置默认的profile-->
<servlet><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>spring.profiles.default</param-name><param-value>dev</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
2.有条件的bean
假设你希望一个或多个bean只有在应用的类路径下包含特定的库时才创建。或者我们希望某个bean只有当另外某个特定的bean也声明了之后才会创建。我们还可能要求只有某个特定的环境变量设置之后才会创建某个bean。在Spring4之前,很难实现这种级别的条件化配置,但是Spring4引入了一个新的@Conditioinal注解,他可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean就会被忽略。
有条件的bean一般在java配置注入bean的方法中使用到。
@Configuration
public class ConditionalConfig {@Bean@Conditional(MagicExistsConditional.class) //条件化的创建beanpublic MagicBean magicBean() {return new MagicBean();}
}
public class MagicExistsConditional implements Condition{@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Environment evn = context.getEnvironment();return evn.containsProperty("magic");}}
如你所见,设置给@Conditional的类可以是任意实现了Condition接口的的类型。而实现这个接口只需要实现matches方法,如果matches方法返回true就创建该bean,如果返回false则不创建bean,上例中我们就是根据环境变量中是否存在magic变量,来决定matches的返回值,进而决定是否创建MagicBean的。
但是在实际生产中,ConditionContext context, AnnotatedTypeMetadata metadata这两个参数可以对类中的其他信息进行判断,有兴趣可以查一下这两个类的api。
3.处理自动装配的歧义性
如果不仅有一个bean能够匹配结果的话,这种歧义性阻碍Spring自动装配属性、构造器参数或方法参数。 下面是一个例子:
@Autowired
public void setDessert(Dessert dessert){this.dessert = dessert;
}
@Component
public class Cake implements Dessert{...}
@Component
public class Cookies implements Dessert{...}
@Component
public class IceCream implements Dessert{...}
在这里,当Spring试图自动装配setDessert()中的Dessert参数时,它并没有唯一、无歧义的可选值。因而,Spring会抛出NoUniqueBeanDefinitionException;
解决方案1:将其中一个bean设置为首选
@Component
@Primary
public class Cake implements Dessert{...}
或者在xml中
<bean id = "iceCream"
class = "com.desserteater.Icecream"
primary = "true">
</bean>
解决方法2:使用限定符(qualifier)来帮助Spring将可选的bean的范围缩小
@Autowired
@Qualifier("cake")
public void setDessert(Dessert dessert){this.dessert = dessert;
}
4、bean的作用域
- 单例(singleton):在整个应用中,只创建bean的一个实例。
- 原型(prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
- 会话(Session):在Web应用中,为每个会话创建一个bean实例。
- 请求(Request):在Web应用中,为每个请求创建一个bean实例。
单例是默认的作用域,但是正如之前所述,对于易变的类型,这并不合适。如果选择其他的作用域,要使用@Scope注解,他可以与@Component(自动装配)或@Bean(JavaConfig)一起使用。
例如,如果你使用组件扫描来发现声明bean,那么你可以在bean的类上使用@Scope注解,将其声明为原型bean,如下:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//@Scope("prototype")
public class Notepad{...}
或者
<bean id="notepad"class="com.myapp.Notepad"scope="prototype" />
使用会话和请求作用域
@Component
@Scope(value=WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart(){...}
这里,我们将value设置成了WebApplicationContext中的SCOPE_SESSION常量(它的值是session)。这会告诉Spring为Web应用中的每个会话创建一个ShoppingCart。这会创建多个ShoppingCart bean 实例,但是对于给定的会话只会创建一个实例,在当前会话相关的操作中,这个bean实际上相当于单例。
@Scope同时还有一个proxyMode属性,它被设置成了ScopedProxyMode.INTERFACES。这个属性解决了将会话或请求作用域的bean注入到单例bean中所遇到的问题。作用域代理能够延迟注入请求和会话作用域的bean。
在xml中注入:
<bean id="cart"class="com.myapp.ShoppingCart"scope="session"><aop:scoped-proxy />
</bean>
Spring之高级装配(二)相关推荐
- spring(3)高级装配
[0]README 0)本文部分文字描述转自:"Spring In Action(中/英文版)",旨在review spring(3)高级装配 的相关知识: [1]环境与prof ...
- 《Spring实战》读书笔记-第3章 高级装配
<Spring实战>是学习Spring框架的一本非常经典的书籍,之前阅读了这本书,只是在书本上写写画画,最近整理了一下<Spring实战>的读书笔记,通过博客的方式进行记录分享 ...
- 《Spring实战》读书笔记-第3章 高级装配,zookeeper原理图
文章目录 3.1 环境与profile 3.2 条件化的bean 3.3 处理自动装配的歧义性 3.4 Bean的作用域 3.5 运行时植注入 3.6 小结 本章内容: Spring profile ...
- 《Spring实战》读书笔记-第3章 高级装配,字节跳动四面技术面
当自动装配bean时,遇到多个实现类的情况下,就出现了歧义,例如: @Autowired public void setDessert(Dessert dessert) { this.dessert ...
- 《Spring实战》读书笔记-第3章 高级装配,最新Java大厂高频面试题
<jee:jndi-lookup id="dataSource" lazy-init="true" jndi-name="jdbc/myData ...
- spring面试题(二)
目录 硅谷 一 .请写出 spring 中常用的依赖注入方式. 二 .简述Spring中IOC容器常用的接口和具体的实现类 三 .简述Spring中如何基于注解配置Bean和装配Bean 四. 说 ...
- Spring Boot自动装配原理详解
目录 1.环境和依赖 1.1.spring boot版本 1.2.依赖管理 2.自动装配 2.1.流程概述 2.2.三大步前的准备工作 2.2.1.注解入口 2.2.2.获取所有配置类 2.3.获取过 ...
- 【Spring】—— 自动装配
一.Spring中装配bean的方式 1.在XML中显式配置 2.在Java中进行显式配置 3.隐士的bean发现机制和自动装配 二.自动装配示例 1.在需要装配到其他bean中的类中加入@Compo ...
- spring Bean自动装配
spring Bean自动装配 自动装配是使用spring满足bean依赖的一种方式. spring会在应用上下文中为某个bean寻找其依赖的bean. spring自动装配需要从两个角度来实现,或者 ...
最新文章
- php 语句插入失败,php – Mysqli准备语句插入不插入
- PHP学习笔记-PHP与JavaScript的交互
- vue案例-计数器.html
- 扩散(洛谷-P1661)
- ASP.NET实现多域名多网站共享Session值
- Struts2教程3:struts.xml常用配置解析
- 小程序 · 云开发快速入门与实战
- Wiki系列(一):Wiki系统选择
- android 清理系统垃圾,安卓手机清理系统垃圾方法汇总
- 计算机软件工程学校排名,软件工程专业全国高校排名前十
- 237. 删除链表中的节点 (Delete Node in a Linked List)
- 原来 Elasticsearch 还可以这么理解
- 关于vue组件引用外部Js数值和方法出现的问题
- 谈谈Python的Flask框架学习与福利分享
- 计算机网络超时重传时间,TCP超时重传机制
- 条码打印软件引用其他对象内容的方法
- 小学教师计算机校本培训计划,中小学教师信息技术应用校本培训方案
- 【pycharm环境搭建(python脚本编辑器)】
- 【梦幻连连连】源码分析(二)
- UVA - 1640 The Counting Problem (数位dp)
热门文章
- shell脚本报错:-bash: xxx: /bin/sh^M: bad interpreter: No such file or directory
- VS2008部分使用技巧
- TCP的拥塞控制--慢启动,拥塞避免,快重传,快速恢复
- 最强新一代消息系统,没有之一,不接受反驳!
- 基于LZ77算法的文件压缩
- LiveVideoStackCon 2022 上海站 专题抢先看(4)
- 高性能视频推理引擎优化技术
- BBR及其在实时音视频领域的应用
- 1.65亿人次扫码登记的背后,是TBase的秒级返回
- 1024程序猿节:揭秘腾讯老中青三代程序猿工位